140 lines
3.1 KiB
NASM
140 lines
3.1 KiB
NASM
global main
|
|
|
|
extern printf
|
|
|
|
struc timespec ; структура, в которой линукс хранит время. Тут нужна для удобства в будущем
|
|
.tv_sec: resq 1
|
|
.tv_nsec: resq 1
|
|
endstruc
|
|
|
|
%include "timer.inc"
|
|
|
|
section .note.GNU-stack
|
|
|
|
section .data
|
|
example: times 128 db 127
|
|
|
|
section .bss
|
|
; uses timespec model
|
|
start: resq 2
|
|
finish: resq 2
|
|
deltatime: resq 2
|
|
|
|
section .text
|
|
|
|
%macro PUSH_M 1-*
|
|
%rep %0
|
|
push %1
|
|
%rotate 1
|
|
%endrep
|
|
%endmacro
|
|
|
|
%macro RPOP_M 1-*
|
|
%rotate -1
|
|
%rep %0
|
|
pop %1
|
|
%rotate -1
|
|
%endrep
|
|
%endmacro
|
|
|
|
%define CLOCK_REALTIME 0
|
|
%macro TIME_1_000_000 0-1+ ; принимает команду, которую будет пытаться обмерить по времени
|
|
PUSH_M rax, rdi, rsi, rcx
|
|
mov rax, 228 ; Время начала
|
|
mov rdi, CLOCK_REALTIME
|
|
mov rsi, start
|
|
syscall
|
|
RPOP_M rax, rdi, rsi, rcx
|
|
|
|
mov rcx, 10000000000; выполняем миллион раз
|
|
%%loop:
|
|
%1
|
|
loop %%loop
|
|
|
|
PUSH_M rax, rdi, rsi, rcx
|
|
mov rax, 228 ; Время конца
|
|
mov rdi, CLOCK_REALTIME
|
|
mov rsi, finish
|
|
syscall
|
|
RPOP_M rax, rdi, rsi, rcx
|
|
|
|
; считаем секунды
|
|
push rax ; можно было бы оптимизировать, но мне лень макросы переписывать
|
|
mov rax, [finish + timespec.tv_sec]
|
|
sub rax, [start + timespec.tv_sec]
|
|
mov [deltatime + timespec.tv_sec], rax
|
|
|
|
; считаем наносекунды
|
|
mov rax, [finish + timespec.tv_nsec]
|
|
sub rax, [start + timespec.tv_nsec]
|
|
jns %%save_result
|
|
dec qword [deltatime + timespec.tv_sec] ; занимаем миллиард наносекунд
|
|
add rax, 1000000000 ; прибавляем занятый разряд
|
|
%%save_result:
|
|
mov [deltatime + timespec.tv_nsec], rax
|
|
pop rax
|
|
%endmacro
|
|
|
|
%macro PRINT_DELTATIME 1
|
|
;sub rsp, 8
|
|
mov rdi, str_template
|
|
mov rsi, %1
|
|
mov rdx, [deltatime + timespec.tv_sec]
|
|
mov rcx, [deltatime + timespec.tv_nsec]
|
|
call printf
|
|
;add rsp, 8
|
|
%endmacro
|
|
|
|
main:
|
|
push rbp
|
|
mov rbp, rsp
|
|
sub rsp, 16
|
|
xor rax, rax ; поскольку приходим сюда из компилятора, лучше обнулить
|
|
TIME_1_000_000
|
|
PRINT_DELTATIME nop_command
|
|
|
|
TIME_1_000_000 inc rax
|
|
PRINT_DELTATIME reg_command
|
|
|
|
mov rax, example
|
|
TIME_1_000_000 inc byte [rax]
|
|
PRINT_DELTATIME rel_reg
|
|
|
|
mov rax, example
|
|
xor rbx, rbx
|
|
TIME_1_000_000 inc byte [rax + rbx]
|
|
PRINT_DELTATIME ind_base
|
|
|
|
mov rax, example
|
|
xor rbx, rbx
|
|
TIME_1_000_000 inc byte [rax + rbx + 122]
|
|
PRINT_DELTATIME ind_base_disp
|
|
|
|
; Под конец давайте посчитаем тактовую частоту на примере той же самой команды
|
|
rdtsc
|
|
mov [rbp - 4], edx
|
|
mov [rbp - 8], eax
|
|
mov rcx, 10000000000
|
|
mov rax, example
|
|
xor rbx, rbx
|
|
.loop:
|
|
inc byte [rax + rbx + 122]
|
|
loop .loop
|
|
rdtsc
|
|
sub eax, [rbp - 8]
|
|
sbb edx, [rbp - 4]
|
|
mov [rbp - 8], eax
|
|
mov [rbp - 4], edx
|
|
|
|
mov [rbp - 16], rsp
|
|
and rsp, -16
|
|
mov rdi, tick_count
|
|
mov rsi, [rbp - 8]
|
|
call printf
|
|
|
|
mov rsp, rbp
|
|
pop rbp
|
|
xor rax, rax ; сообщаем gcc, что все закончилось успешно
|
|
ret
|
|
|