Files
solutions/04-addr-methods/task2.asm

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