5 Commits

Author SHA1 Message Date
541524bd6f feat: первый прототип для 2 пунтка написан 2024-10-01 15:58:31 +03:00
df80a7190e feat: написаны приготовления для 2 пункта
В приготовления входит макрос для замера времени и предварительно записанные строки для printf
2024-10-01 12:52:23 +03:00
4594912561 feat: решен первый пункт
Этот пункт действительно предполагает просто воспользоваться всеми типами адресации
2024-10-01 12:51:05 +03:00
95df24eaa5 feat: добавлена отдельная логика компиляции для task2
Дело в том, что там я намереваюсь воспользоваться фукнциями стандратной библиотеки Си, поэтому процесс компиляции должен быть особым
2024-10-01 12:49:35 +03:00
53a82c8ea0 feat: скопирован старый Makefile 2024-09-30 15:16:32 +03:00
6 changed files with 271 additions and 0 deletions

67
01-asm-basics/time.asm Normal file
View File

@ -0,0 +1,67 @@
global main
extern printf
%define CLOCK_REALTIME 0
; struct timespec { time_t tv_sec; long tv_nsec; }
struc timespec
.tv_sec: resq 1
.tv_nsec: resq 1
endstruc
section .note.GNU-stack ; чтобы не жаловался линкер
section .bss
start: ; uses timespec model
times 2 resq 1
finish:
times 2 resq 1
section .data
fstring db "Operations took %ul seconds and %ul milliseconds", 10, 0
flen equ $-fstring
section .text
main: ; лично в моей системе time_t представляет из себя long int
mov rax, 228 ; Системный вызов получения времени
mov rdi, CLOCK_REALTIME
mov rsi, start
syscall
; insert your code here
mov rcx, 20000
looper:
mov rax, start
loop looper
mov rax, 228
mov rdi, CLOCK_REALTIME
mov rsi, finish
syscall
; считаем время для секунда и миллисекунд
; секунды
mov rsi, [finish + timespec.tv_sec]
sub rsi, [start + timespec.tv_sec]
; миллисекунды
mov rdx, [finish + timespec.tv_nsec]
sub rdx, [start + timespec.tv_nsec]
mov rdi, fstring
mov rax, 0
sub rsp, 8
call printf
add rsp, 8
exit:
mov rax, 60
mov rdi, 0
syscall

13
03-asm-bios/Makefile Normal file
View File

@ -0,0 +1,13 @@
ASM = nasm
ASM_FLAGS = -felf64 -g
LINK = ld
%: %.o
$(LINK) -o $@ $^
%.o: %.asm
$(ASM) $(ASM_FLAGS) $^ -o $@
clean:
rm -f *.o
rm -f $(subst .asm, $(empty), $(wildcard *.asm))

18
04-addr-methods/Makefile Normal file
View File

@ -0,0 +1,18 @@
ASM = nasm
CXX = gcc
CXX_FLAGS = -Os -static
ASM_FLAGS = -felf64 -g
LINK = ld
task2: task2.o
$(CXX) $(CXX_FLAGS) $^ -o $@
%: %.o
$(LINK) -o $@ $^
%.o: %.asm
$(ASM) $(ASM_FLAGS) $^ -o $@
clean:
rm -f *.o
rm -f $(subst .asm, $(empty), $(wildcard *.asm))

33
04-addr-methods/task1.asm Normal file
View File

@ -0,0 +1,33 @@
global _start
section .data
%macro FILL_ASC 1
%assign NUM 0
%rep %1
db NUM
%assign NUM NUM + 1
%endrep
%endmacro
example: FILL_ASC 256
section .text
_start:
; В качестве базы возьму inc
; регистровая
inc ecx
mov rax, example
; косвенно-регистровая
inc byte [rax]
; "Индексно-базовая", хотя у меня почти все может быть базой
inc byte [rax + rbx]
; "Индексно-базовая" со смещением
inc byte [rax + rbx + 122]
; Ну в целом... все
mov rax, 60
mov rdi, 0
syscall

129
04-addr-methods/task2.asm Normal file
View File

@ -0,0 +1,129 @@
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, 1000000000 ; выполняем миллион раз
%%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]
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:
; В качестве базы возьму inc
; регистровая
;inc ecx
;mov rax, example
;xor rbx, rbx
;; косвенно-регистровая
;inc byte [rax]
;; "Индексно-базовая", хотя у меня почти все может быть базой
;inc byte [rax + rbx]
;; "Индексно-базовая" со смещением
;inc byte [rax + rbx + 122]
xor rax, rax ; поскольку приходим сюда из компилятора, лучше обнулить
TIME_1_000_000
nop
PRINT_DELTATIME nop_command
nop ; для дебага
TIME_1_000_000 inc rax
nop
PRINT_DELTATIME reg_command
nop
mov rax, example
TIME_1_000_000 inc byte [rax]
nop
PRINT_DELTATIME rel_reg
nop
mov rax, example
xor rbx, rbx
TIME_1_000_000 inc byte [rax + rbx]
nop
PRINT_DELTATIME ind_base
nop
mov rax, example
xor rbx, rbx
TIME_1_000_000 inc byte [rax + rbx + 122]
nop
PRINT_DELTATIME ind_base_disp
nop
xor rax, rax ; сообщаем gcc, что все закончилось успешно
ret

11
04-addr-methods/timer.inc Normal file
View File

@ -0,0 +1,11 @@
section .data
str_template: db "Command %s took %lld seconds and %lld nanoseconds to execute 1 000 000 000 times", 10, 0
template_len equ $-str_template
nop_command: db '`empty loop`', 0
reg_command: db '`inc ebx`', 0
rel_reg: db '`inc byte [rax]`', 0
ind_base: db '`inc byte [rax + rbx]`', 0
ind_base_disp: db '`inc byte [rax + rbx + 122]`', 0