From e1aeb3f2df1c18d7b4745c4e9ebd870fd9e980f0 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Mon, 23 Sep 2024 20:45:46 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20=D0=BF=D1=80=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D1=82=D0=B8=D0=BF=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Прототип еще не тестировался --- 03-asm-bios/task4.asm | 59 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/03-asm-bios/task4.asm b/03-asm-bios/task4.asm index 0270f84..ed69cae 100644 --- a/03-asm-bios/task4.asm +++ b/03-asm-bios/task4.asm @@ -55,6 +55,11 @@ section .text %endrep %endmacro +%macro PUSHR8 1; закинуть восьмибитный регистр в стек + dec rsp + mov [rsp], %1 +%endmacro + ; Передачу аргументов будем делать при помощи ABI - стандартная практика для linux ; Аргументы передаются в следующем порядке: rdi, rsi, rdx, rcx, r8, r9. Все, что не влезло, пушится в стек ; У передачи через стек тоже есть особенности, но их мы пока касаться не будем @@ -68,7 +73,7 @@ clean_print_buf: ; none -> void RPOP_M rax, rcx, rdi ret -print_from_buf: ; word -> void +print_from_buf: ; qword -> void; пытается вывести данные из буфера. аргумент не может быть больше 1024 PUSH_M rax, rsi, rdx, rdi ; сохраним регистры, которые точно попортим mov rdx, rdi ; сколько выводить, в rdi содержится единственный аргумент mov rsi, print_buf ; откуда выводить. Адрес буфера @@ -99,11 +104,44 @@ poll_stdin: RPOP_M rdi, rsi, rdx ret +print_number: ; qword (rdi) -> void + ; наша задача - сформировать массив символов. + ; Ну а раз мы не знаем точно сколько их будет, формировать его будем прямо в стеке. нам повезло, что он растет вниз + ; Нам очень повезло, что он растет вниз + ; создадим 2 локальные переменные - одну для размера массива, другую для делителя + push rbp + PUSH_M rdx, rdi, rsi ; сохранять регистры обязательно надо до того, как писать в стек символы + ; создаем базу для адресации. Тогда первая будет на rbp - 8 - делитель, а вторая на rbp - 16 - количество + mov rbp, rsp + ; [WARNING] тут надо будет сохранить регистры + sub rsp, 16 ; выделяем место под 2 переменные + mov qword [rbp - 8], 10 ; пусть и жирно, но операнд обязан быть 64 разрядным для корректного деления + mov qword [rbp - 16], 0 ; счетчик + mov rax, rdi + .division_loop: + xor rdx, rdx ; обнулим найденый остаток. (он просто еще и при делении принимает участие) + div qword [rbp - 8] + DIGIT_TO_ASCII dl + PUSHR8 dl ; поскольку в процессор не завезли возможность закинуть в стек 8 битный регистр, я им немного помог макросами + inc qword [rbp - 16] ; увеличиваем счетчик на единицу + test rax, rax ; делает and поразрядное с самим собой. Меня интересует, лежит ли в rax ноль + jnz .division_loop ; если в rax не ноль, то продолжаем цикл + ; выводим число + mov rax, 1 + mov rdi, STDOUT + mov rsi, rsp + mov rdx, [rbp-16] + add rsp, 16 ; освобождаем память + RPOP_M rdx, rdi, rsi + pop rbp + _start: mov rbp, rsp ; Создадим 2 локальные переменные для аккумулятора размером 8 байт и для математических нужд 8 байт. ; аккумулятор будет по адресу rbp - 8, а временная по rbp - 16 sub rsp, 16 + ; потом я не удержался и завел еще одну переменную - сколько мы успели написать в массив + sub rsp, 2 ; массив все равно размером всего 512, делать переменную больше нет смысла. rbp - 18 mov rsi, input_buf mov rdi, array @@ -118,7 +156,8 @@ _start: dec rcx mov rax, [rbp - 8] stosq - mov QWORD [rbp - 8], 0 + inc word [rbp - 18] + mov qword [rbp - 8], 0 test rcx, rcx jz .check_buf @@ -146,6 +185,22 @@ _start: test BYTE [revents], POLLIN jnz .read_loop + ; Теперь выведем прочитанный массив на экран + xor rcx, rcx + mov cx, [rbp - 18] + .output_loop: + mov rsi, array + lodsq + mov rdi, rax + call print_number + mov byte [print_buf], ' ' + mov rdi, 1 + call print_from_buf ; печатаем ровно 1 пробел + loop .output_loop + mov byte [print_buf], `\n` + mov rdi, 1 + call print_from_buf + exit: mov rax, 60 mov rdi, 0