Compare commits
17 Commits
labs/02
...
labs/cours
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cf6ecc535 | |||
| 34ed7f9fcc | |||
| 08ae2e64c9 | |||
| 009f4d3bda | |||
| b161ff5465 | |||
| 51e5f729da | |||
| 8fc6112f58 | |||
| 23b82657d4 | |||
| 78a4638401 | |||
| e1aeb3f2df | |||
| ed21dfe07a | |||
| 6c1198df73 | |||
| 58897fedb7 | |||
| 85ba08abb9 | |||
| 51e220410a | |||
| 49d3c02d7d | |||
| daec968bcb |
@ -16,9 +16,7 @@ _start:
|
|||||||
mov rdi, dest
|
mov rdi, dest
|
||||||
mov rcx, s_size
|
mov rcx, s_size
|
||||||
|
|
||||||
.loop:
|
|
||||||
rep movsb
|
rep movsb
|
||||||
loop .loop
|
|
||||||
|
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
mov rdi, 0
|
mov rdi, 0
|
||||||
|
|||||||
13
03-asm-bios/Makefile
Normal file
13
03-asm-bios/Makefile
Normal 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))
|
||||||
@ -2,3 +2,13 @@
|
|||||||
|
|
||||||
## Ассемблер и функции BIOS
|
## Ассемблер и функции BIOS
|
||||||
|
|
||||||
|
В этой работе намного проще посмотреть непосредственно решения и почитать комментарии к коду, чем читать теоретическое приложение к работе. Если вам все же что-то не понятно - кидайте в issues
|
||||||
|
|
||||||
|
Впрочем зная, что основная масса народу не будет делать эту лабу так, как сделал ее я, сюда вряд ли кто-то заглянет)
|
||||||
|
|
||||||
|
### Касаемо Makefile
|
||||||
|
|
||||||
|
Для того чтобы не писать много команд для однотипной и монотонной сборки проекта, был написан простой Makefile. Однако работает он следующим образом: он принимает название цели сборки и ищет файл с именем цели и расширением .asm. Если не находит - не собирает цель.
|
||||||
|
|
||||||
|
Важно заметить, что он не умеет линковать другие файлы в ассемблер, потому что написан был не для этого. Он просто берет голый файл на NASM (обязательно) и выдает 64-битный ELF из этого единственного файла. Если вам необходимо что-то прилинковать к ассемблеру, то увы, придется собирать проект вручную или менять этот makefile
|
||||||
|
|
||||||
|
|||||||
81
03-asm-bios/task2.asm
Normal file
81
03-asm-bios/task2.asm
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
global _start
|
||||||
|
|
||||||
|
%define STDIN 0
|
||||||
|
%define STDOUT 1
|
||||||
|
%define STDERR 2
|
||||||
|
|
||||||
|
section .data
|
||||||
|
src db 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
|
||||||
|
src_size equ $-src
|
||||||
|
|
||||||
|
; резервируем 1 килобайт для буффера ввода и вывода
|
||||||
|
; также в отдельной переменной сохраняем размер этого буфера
|
||||||
|
print_buf: times 1024 db 0
|
||||||
|
buf_size equ $-print_buf
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
%macro DIGIT_TO_ASCII 1 ; макрос, принимающий один регистр
|
||||||
|
add %1, '0'
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PUSH_M 1-* ; push many; пушит в порядке следования
|
||||||
|
%rep %0
|
||||||
|
push %1
|
||||||
|
%rotate 1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro POP_M 1-* ; pop many. читает в порядке следования
|
||||||
|
%rep %0
|
||||||
|
pop %1
|
||||||
|
%rotate 1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro RPOP_M 1-* ; pop many. читает в обратном порядке
|
||||||
|
%rotate -1
|
||||||
|
%rep %0
|
||||||
|
pop %1
|
||||||
|
%rotate -1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; Передачу аргументов будем делать при помощи ABI - стандартная практика для linux
|
||||||
|
; Аргументы передаются в следующем порядке: rdi, rsi, rdx, rcx, r8, r9. Все, что не влезло, пушится в стек
|
||||||
|
; У передачи через стек тоже есть особенности, но их мы пока касаться не будем
|
||||||
|
|
||||||
|
print_from_buf: ; word -> void
|
||||||
|
|
||||||
|
PUSH_M rax, rsi, rdx, rdi ; сохраним регистры, которые точно попортим
|
||||||
|
mov rdx, rdi ; сколько выводить, в rdi содержится единственный аргумент
|
||||||
|
mov rsi, print_buf ; откуда выводить. Адрес буфера
|
||||||
|
mov rdi, STDOUT; куда выводить. Дескриптор файла. В нашем случае стандартного вывода
|
||||||
|
mov rax, 1
|
||||||
|
syscall
|
||||||
|
|
||||||
|
RPOP_M rax, rsi, rdx, rdi ; вернем значения регистров
|
||||||
|
ret
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mov rcx, src_size
|
||||||
|
mov rsi, src
|
||||||
|
mov rdi, print_buf
|
||||||
|
|
||||||
|
xor rax, rax ; обнуляем регистр
|
||||||
|
.transfer: ; в цикле передаем данные, попутно конвертируя их в ascii
|
||||||
|
lodsb
|
||||||
|
DIGIT_TO_ASCII rax
|
||||||
|
stosb
|
||||||
|
loop .transfer
|
||||||
|
|
||||||
|
mov [rdi + 1], BYTE `\n` ; Чтобы система не ругалась на отсутствие переноса
|
||||||
|
|
||||||
|
mov rdi, src_size
|
||||||
|
call print_from_buf
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mov rax, 60
|
||||||
|
mov rdi, 0
|
||||||
|
syscall
|
||||||
|
|
||||||
219
03-asm-bios/task4.asm
Normal file
219
03-asm-bios/task4.asm
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
global _start
|
||||||
|
|
||||||
|
%define STDIN 0
|
||||||
|
%define STDOUT 1
|
||||||
|
%define STDERR 2
|
||||||
|
|
||||||
|
section .data
|
||||||
|
|
||||||
|
; резервируем 1 килобайт для буффера ввода и вывода
|
||||||
|
; также в отдельной переменной сохраняем размер этого буфера
|
||||||
|
print_buf: times 1024 db 0
|
||||||
|
buf_size equ $-print_buf
|
||||||
|
|
||||||
|
input_buf: times 1024 db 0 ; буфер, в который будут читаться символы со стандартного ввода
|
||||||
|
input_size equ $-input_buf
|
||||||
|
|
||||||
|
array: times 512 dq 0 ; молимся, чтобы никому не пришло в голову писать так много
|
||||||
|
arr_size equ $-array
|
||||||
|
|
||||||
|
; Для poll
|
||||||
|
%define POLLIN 0x001 ; Есть ли что почитать с буфера ввода. Понадобится для продолжения ввода
|
||||||
|
input_pollfd: dd STDIN
|
||||||
|
dw POLLIN
|
||||||
|
revents: dw 0 ; возвращаемые события
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
%macro DIGIT_TO_ASCII 1 ; макрос, принимающий один аргумент (регистр или память)
|
||||||
|
add %1, '0'
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro ASCII_TO_DIGIT 1 ; макрос, принимающий один аргумент (регистр или память)
|
||||||
|
sub %1, '0'
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PUSH_M 1-* ; push many; пушит в порядке следования
|
||||||
|
%rep %0
|
||||||
|
push %1
|
||||||
|
%rotate 1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro POP_M 1-* ; pop many. читает в порядке следования
|
||||||
|
%rep %0
|
||||||
|
pop %1
|
||||||
|
%rotate 1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro RPOP_M 1-* ; pop many. читает в обратном порядке
|
||||||
|
%rotate -1
|
||||||
|
%rep %0
|
||||||
|
pop %1
|
||||||
|
%rotate -1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro PUSHR8 1; закинуть восьмибитный регистр в стек
|
||||||
|
dec rsp
|
||||||
|
mov [rsp], %1
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; Передачу аргументов будем делать при помощи ABI - стандартная практика для linux
|
||||||
|
; Аргументы передаются в следующем порядке: rdi, rsi, rdx, rcx, r8, r9. Все, что не влезло, пушится в стек
|
||||||
|
; У передачи через стек тоже есть особенности, но их мы пока касаться не будем
|
||||||
|
|
||||||
|
clean_print_buf: ; none -> void
|
||||||
|
PUSH_M rax, rcx, rdi
|
||||||
|
mov rcx, buf_size
|
||||||
|
mov rdi, print_buf
|
||||||
|
xor rax, rax ; будем заносить нули во всю память
|
||||||
|
rep stosb
|
||||||
|
RPOP_M rax, rcx, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_from_buf: ; qword -> void; пытается вывести данные из буфера. аргумент не может быть больше 1024
|
||||||
|
PUSH_M rax, rsi, rdx, rdi ; сохраним регистры, которые точно попортим
|
||||||
|
mov rdx, rdi ; сколько выводить, в rdi содержится единственный аргумент
|
||||||
|
mov rsi, print_buf ; откуда выводить. Адрес буфера
|
||||||
|
mov rdi, STDOUT; куда выводить. Дескриптор файла. В нашем случае стандартного вывода
|
||||||
|
mov rax, 1
|
||||||
|
push rcx
|
||||||
|
syscall
|
||||||
|
pop rcx
|
||||||
|
RPOP_M rax, rsi, rdx, rdi ; вернем значения регистров
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_to_buf: ; none -> void. Пытается заполнить буфер из стандартного ввода
|
||||||
|
PUSH_M rdi, rsi, rdx
|
||||||
|
mov rdi, STDIN ; откуда читать (дескриптор файла)
|
||||||
|
mov rsi, input_buf ; куда читать
|
||||||
|
mov rdx, input_size ; Сколько пытаемся читать
|
||||||
|
mov rax, 0 ; системный вызов чтения
|
||||||
|
syscall
|
||||||
|
RPOP_M rdi, rsi, rdx ; rax содержит количество прочитанных байт, а это важно
|
||||||
|
ret
|
||||||
|
|
||||||
|
poll_stdin:
|
||||||
|
PUSH_M rdi, rsi, rdx
|
||||||
|
mov rsi, 1 ; следим только за одним потоком
|
||||||
|
mov rax, 7 ; poll syscall
|
||||||
|
mov rdi, input_pollfd
|
||||||
|
mov rsi, 1 ; одна структура данных (изначально просто вызов принимает кучу таких)
|
||||||
|
mov rdx, 0 ; не ждать
|
||||||
|
syscall
|
||||||
|
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] тут надо будет сохранить регистры
|
||||||
|
push rsp ; сохраню, потому что после всей вакханалии я концов не сыщу
|
||||||
|
sub rsp, 16 ; выделяем место под 3 переменные
|
||||||
|
mov qword [rbp - 16], 10 ; пусть и жирно, но операнд обязан быть 64 разрядным для корректного деления
|
||||||
|
mov qword [rbp - 24], 0 ; счетчик
|
||||||
|
mov rax, rdi
|
||||||
|
push byte 0 ; при выводе он ориентируется на это как на конец строки
|
||||||
|
.division_loop:
|
||||||
|
xor rdx, rdx ; обнулим найденый остаток. (он просто еще и при делении принимает участие)
|
||||||
|
div qword [rbp - 16]
|
||||||
|
DIGIT_TO_ASCII dl
|
||||||
|
PUSHR8 dl ; поскольку в процессор не завезли возможность закинуть в стек 8 битный регистр, я им немного помог макросами
|
||||||
|
inc qword [rbp - 24] ; увеличиваем счетчик на единицу
|
||||||
|
test rax, rax ; делает and поразрядное с самим собой. Меня интересует, лежит ли в rax ноль
|
||||||
|
jnz .division_loop ; если в rax не ноль, то продолжаем цикл
|
||||||
|
; выводим число
|
||||||
|
mov rax, 1
|
||||||
|
mov rdi, STDOUT
|
||||||
|
mov rsi, rsp
|
||||||
|
mov rdx, [rbp-24] ; уже не надо очищать, потому что в конце я просто восстановлю как было
|
||||||
|
push rcx
|
||||||
|
syscall
|
||||||
|
pop rcx
|
||||||
|
|
||||||
|
mov rsp, [rbp - 8]
|
||||||
|
RPOP_M rdx, rdi, rsi
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
_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
|
||||||
|
.read_loop:
|
||||||
|
call read_to_buf ; системный вызов read вернет количество прочитаных байтов
|
||||||
|
mov rcx, rax ; сколько байтов прочиталось, столько и обработаем
|
||||||
|
; обработаем информацию
|
||||||
|
xor rax, rax ; обнулим на всякий пожарный
|
||||||
|
jmp .read_byte
|
||||||
|
|
||||||
|
.separator_occured:
|
||||||
|
dec rcx
|
||||||
|
mov rax, [rbp - 8]
|
||||||
|
stosq
|
||||||
|
xor rax, rax
|
||||||
|
inc word [rbp - 18]
|
||||||
|
mov qword [rbp - 8], 0
|
||||||
|
test rcx, rcx
|
||||||
|
jz .check_buf
|
||||||
|
|
||||||
|
.read_byte: ; цикл чтения
|
||||||
|
lodsb
|
||||||
|
; проверим, цифра ли это. Если нет, то записываем в память то, что хранилось в локальной переменной
|
||||||
|
cmp al, '0'
|
||||||
|
jl .separator_occured
|
||||||
|
cmp al, '9'
|
||||||
|
jg .separator_occured
|
||||||
|
|
||||||
|
ASCII_TO_DIGIT al ; Если цифра, то конвертируем ее из ascii
|
||||||
|
; Поскольку умножение и деление можно сделать только через регистр, придется извратиться
|
||||||
|
PUSH_M rax, rdx
|
||||||
|
mov rax, [rbp - 8]
|
||||||
|
mov qword [rbp - 16], 10
|
||||||
|
mul qword [rbp - 16]
|
||||||
|
mov [rbp - 8], rax
|
||||||
|
RPOP_M rax, rdx
|
||||||
|
add [rbp - 8], rax ; результат деления запишем в локальную переменную
|
||||||
|
loop .read_byte ; читаем буфер ввода до конца
|
||||||
|
|
||||||
|
.check_buf:
|
||||||
|
call poll_stdin
|
||||||
|
test dword [revents], POLLIN
|
||||||
|
jnz .read_loop
|
||||||
|
|
||||||
|
; Теперь выведем прочитанный массив на экран
|
||||||
|
xor rcx, rcx
|
||||||
|
mov cx, [rbp - 18]
|
||||||
|
mov rsi, array
|
||||||
|
call clean_print_buf
|
||||||
|
.output_loop:
|
||||||
|
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
|
||||||
|
syscall
|
||||||
|
|
||||||
379
coursework/main.asm
Normal file
379
coursework/main.asm
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
global _start
|
||||||
|
|
||||||
|
%define NAME_SIZE 64
|
||||||
|
%define BUFF_SIZE 1024
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
name resb NAME_SIZE
|
||||||
|
buffer resb BUFF_SIZE
|
||||||
|
|
||||||
|
section .data
|
||||||
|
buffer_tail dq buffer
|
||||||
|
iseof db 0
|
||||||
|
|
||||||
|
;strings
|
||||||
|
E_open_file db `Something went wrong while opening file\n`
|
||||||
|
|
||||||
|
section .text
|
||||||
|
read:
|
||||||
|
push rcx
|
||||||
|
push r11
|
||||||
|
mov rax, 0
|
||||||
|
syscall
|
||||||
|
pop r11
|
||||||
|
pop rcx
|
||||||
|
ret
|
||||||
|
|
||||||
|
write:
|
||||||
|
push rcx
|
||||||
|
push r11
|
||||||
|
mov rax, 1
|
||||||
|
syscall
|
||||||
|
pop r11
|
||||||
|
pop rcx
|
||||||
|
ret
|
||||||
|
|
||||||
|
namecmp:
|
||||||
|
.LFB6:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
mov -8[rbp], rdi
|
||||||
|
mov -16[rbp], rsi
|
||||||
|
jmp .L2
|
||||||
|
.L6:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx edx, BYTE [rax]
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
cmp dl, al
|
||||||
|
je .L3
|
||||||
|
mov eax, 0
|
||||||
|
jmp .L4
|
||||||
|
.L3:
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
add QWORD -16[rbp], 1
|
||||||
|
.L2:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
test al, al
|
||||||
|
je .L5
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
test al, al
|
||||||
|
jne .L6
|
||||||
|
.L5:
|
||||||
|
mov eax, 1
|
||||||
|
.L4:
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
openfile:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 32
|
||||||
|
mov -24[rbp], rdi
|
||||||
|
mov rax, -24[rbp]
|
||||||
|
mov esi, 0
|
||||||
|
mov rdi, rax
|
||||||
|
mov eax, 2
|
||||||
|
syscall
|
||||||
|
mov -4[rbp], eax
|
||||||
|
cmp DWORD -4[rbp], 0
|
||||||
|
jns .L8
|
||||||
|
mov rdi, 1
|
||||||
|
mov rsi, E_open_file
|
||||||
|
mov rdx, 40
|
||||||
|
call write
|
||||||
|
mov edi, 1
|
||||||
|
mov rax, 60
|
||||||
|
mov rdi, 1
|
||||||
|
syscall
|
||||||
|
.L8:
|
||||||
|
mov eax, -4[rbp]
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
fill_buffer:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 32
|
||||||
|
mov -20[rbp], edi
|
||||||
|
mov rdx, [buffer_tail]
|
||||||
|
lea rax, [buffer]
|
||||||
|
sub rdx, rax
|
||||||
|
mov eax, 1024
|
||||||
|
sub rax, rdx
|
||||||
|
mov -8[rbp], rax
|
||||||
|
mov rdx, -8[rbp]
|
||||||
|
mov eax, -20[rbp]
|
||||||
|
lea rcx, [buffer]
|
||||||
|
mov rsi, rcx
|
||||||
|
mov edi, eax
|
||||||
|
call read
|
||||||
|
mov -16[rbp], rax
|
||||||
|
cmp QWORD -16[rbp], 1023
|
||||||
|
ja .L11
|
||||||
|
mov BYTE [iseof], 1
|
||||||
|
.L11:
|
||||||
|
lea rdx, [buffer]
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov [buffer_tail], rax
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
find_second_word:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
mov -8[rbp], rdi
|
||||||
|
jmp .L13
|
||||||
|
.L14:
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
.L13:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
cmp al, 32
|
||||||
|
jne .L14
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
find_fullname_end:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
lea rax, [buffer]
|
||||||
|
mov -8[rbp], rax
|
||||||
|
jmp .L17
|
||||||
|
.L20:
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
.L17:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
cmp al, 10
|
||||||
|
jne .L18
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
test al, al
|
||||||
|
jne .L19
|
||||||
|
.L18:
|
||||||
|
lea rax, [buffer+1024]
|
||||||
|
cmp -8[rbp], rax
|
||||||
|
jb .L20
|
||||||
|
.L19:
|
||||||
|
lea rax, [buffer+1024]
|
||||||
|
cmp -8[rbp], rax
|
||||||
|
jne .L21
|
||||||
|
mov eax, 0
|
||||||
|
jmp .L22
|
||||||
|
.L21:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
.L22:
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
pop_fullname:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
sub rsp, 32
|
||||||
|
mov eax, 0
|
||||||
|
call find_fullname_end
|
||||||
|
add rax, 1
|
||||||
|
mov -16[rbp], rax
|
||||||
|
lea rdx, [buffer]
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
sub rax, rdx
|
||||||
|
mov -24[rbp], rax
|
||||||
|
mov QWORD -8[rbp], 0
|
||||||
|
jmp .L24
|
||||||
|
.L25:
|
||||||
|
mov rdx, -16[rbp]
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
lea rcx, [buffer]
|
||||||
|
mov rdx, -8[rbp]
|
||||||
|
add rdx, rcx
|
||||||
|
mov BYTE [rdx], al
|
||||||
|
mov rdx, -16[rbp]
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov BYTE [rax], 0
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
.L24:
|
||||||
|
mov eax, 1024
|
||||||
|
sub rax, -24[rbp]
|
||||||
|
cmp -8[rbp], rax
|
||||||
|
jb .L25
|
||||||
|
mov rax, [buffer_tail]
|
||||||
|
mov rdx, -24[rbp]
|
||||||
|
neg rdx
|
||||||
|
add rax, rdx
|
||||||
|
mov [buffer_tail], rax
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
preprint db `count: `
|
||||||
|
postprint db `\n`
|
||||||
|
|
||||||
|
print_count:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 32
|
||||||
|
mov -24[rbp], rdi
|
||||||
|
mov edx, 8
|
||||||
|
mov rax, preprint
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write
|
||||||
|
jmp .L27
|
||||||
|
.L28:
|
||||||
|
mov rcx, -24[rbp]
|
||||||
|
mov rdx, -3689348814741910323
|
||||||
|
mov rax, rcx
|
||||||
|
mul rdx
|
||||||
|
shr rdx, 3
|
||||||
|
mov rax, rdx
|
||||||
|
sal rax, 2
|
||||||
|
add rax, rdx
|
||||||
|
add rax, rax
|
||||||
|
sub rcx, rax
|
||||||
|
mov rdx, rcx
|
||||||
|
mov eax, edx
|
||||||
|
add eax, 48
|
||||||
|
mov BYTE -1[rbp], al
|
||||||
|
mov rax, -24[rbp]
|
||||||
|
mov rdx, -3689348814741910323
|
||||||
|
mul rdx
|
||||||
|
mov rax, rdx
|
||||||
|
shr rax, 3
|
||||||
|
mov -24[rbp], rax
|
||||||
|
lea rax, -1[rbp]
|
||||||
|
mov edx, 1
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write
|
||||||
|
.L27:
|
||||||
|
cmp QWORD -24[rbp], 0
|
||||||
|
jne .L28
|
||||||
|
mov edx, 1
|
||||||
|
mov rax, postprint
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
get_name:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 40
|
||||||
|
mov -40[rbp], rdi
|
||||||
|
lea rax, [buffer]
|
||||||
|
mov rdi, rax
|
||||||
|
call find_second_word
|
||||||
|
mov -24[rbp], rax
|
||||||
|
mov rax, -24[rbp]
|
||||||
|
mov -8[rbp], rax
|
||||||
|
jmp .L30
|
||||||
|
.L31:
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
.L30:
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
cmp al, 32
|
||||||
|
jne .L31
|
||||||
|
cmp QWORD -8[rbp], 0
|
||||||
|
jne .L32
|
||||||
|
mov eax, -1
|
||||||
|
jmp .L33
|
||||||
|
.L32:
|
||||||
|
mov QWORD -16[rbp], 0
|
||||||
|
jmp .L34
|
||||||
|
.L35:
|
||||||
|
mov rdx, -24[rbp]
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov rcx, -40[rbp]
|
||||||
|
mov rdx, -16[rbp]
|
||||||
|
add rdx, rcx
|
||||||
|
movzx eax, BYTE [rax]
|
||||||
|
mov BYTE [rdx], al
|
||||||
|
add QWORD -16[rbp], 1
|
||||||
|
.L34:
|
||||||
|
mov rdx, -24[rbp]
|
||||||
|
mov rax, -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
cmp rax, -8[rbp]
|
||||||
|
jb .L35
|
||||||
|
mov eax, 0
|
||||||
|
.L33:
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
||||||
|
_start:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 96
|
||||||
|
mov -84[rbp], edi
|
||||||
|
mov -96[rbp], rsi
|
||||||
|
mov rax, -96[rbp]
|
||||||
|
add rax, 8
|
||||||
|
mov rax, [rax]
|
||||||
|
mov rdi, rax
|
||||||
|
call openfile
|
||||||
|
mov -12[rbp], eax
|
||||||
|
mov edx, 64
|
||||||
|
lea rax, [name]
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 0
|
||||||
|
call read
|
||||||
|
mov QWORD -8[rbp], 0
|
||||||
|
mov QWORD -80[rbp], 0
|
||||||
|
mov QWORD -72[rbp], 0
|
||||||
|
mov QWORD -64[rbp], 0
|
||||||
|
mov QWORD -56[rbp], 0
|
||||||
|
mov QWORD -48[rbp], 0
|
||||||
|
mov QWORD -40[rbp], 0
|
||||||
|
mov QWORD -32[rbp], 0
|
||||||
|
mov QWORD -24[rbp], 0
|
||||||
|
.L39:
|
||||||
|
mov eax, 0
|
||||||
|
call find_fullname_end
|
||||||
|
test rax, rax
|
||||||
|
jne .L37
|
||||||
|
mov eax, DWORD -12[rbp]
|
||||||
|
mov edi, eax
|
||||||
|
call fill_buffer
|
||||||
|
.L37:
|
||||||
|
lea rax, -80[rbp]
|
||||||
|
mov rdi, rax
|
||||||
|
call get_name
|
||||||
|
lea rax, -80[rbp]
|
||||||
|
lea rdx, [name]
|
||||||
|
mov rsi, rdx
|
||||||
|
mov rdi, rax
|
||||||
|
call namecmp
|
||||||
|
test eax, eax
|
||||||
|
je .L38
|
||||||
|
add QWORD -8[rbp], 1
|
||||||
|
.L38:
|
||||||
|
mov eax, 0
|
||||||
|
call pop_fullname
|
||||||
|
mov rdx, [buffer_tail]
|
||||||
|
lea rax, [buffer]
|
||||||
|
cmp rdx, rax
|
||||||
|
jne .L39
|
||||||
|
mov rax, -8[rbp]
|
||||||
|
mov rdi, rax
|
||||||
|
call print_count
|
||||||
|
mov eax, 0
|
||||||
|
leave
|
||||||
|
ret
|
||||||
134
coursework/main.c
Normal file
134
coursework/main.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define BUFF_SIZE 1024
|
||||||
|
#define NAME_SIZE 64
|
||||||
|
#define STDIN 0
|
||||||
|
#define STDOUT 1
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
|
char name[NAME_SIZE];
|
||||||
|
char buffer[BUFF_SIZE];
|
||||||
|
char* buffer_tail = buffer; // points on first free symbol
|
||||||
|
|
||||||
|
char iseof = 0;
|
||||||
|
|
||||||
|
int namecmp(char* name1, char* name2)
|
||||||
|
{
|
||||||
|
for (; *name1 && *name2; name1++, name2++)
|
||||||
|
{
|
||||||
|
if (*name1 != *name2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int openfile(char* filename)
|
||||||
|
{
|
||||||
|
int file = open(filename, O_RDONLY);
|
||||||
|
if (file < 0)
|
||||||
|
{
|
||||||
|
puts("Something went wrong while opening file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_buffer(int filedesc)
|
||||||
|
{
|
||||||
|
const size_t tofill = BUFF_SIZE - (buffer_tail - buffer);
|
||||||
|
u64 bytes_read = read(filedesc, buffer, tofill);
|
||||||
|
if (bytes_read < BUFF_SIZE)
|
||||||
|
{
|
||||||
|
iseof = 1;
|
||||||
|
}
|
||||||
|
buffer_tail = buffer + bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* find_second_word(char* start)
|
||||||
|
{
|
||||||
|
for (; *start != ' '; start++);
|
||||||
|
return ++start;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* find_fullname_end()
|
||||||
|
{
|
||||||
|
char* end = buffer;
|
||||||
|
for (; (*end != '\n' || *end == 0)
|
||||||
|
&& end < buffer + BUFF_SIZE; end++);
|
||||||
|
if (end == buffer + BUFF_SIZE)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_fullname() // pops from buffer
|
||||||
|
{
|
||||||
|
char* end = find_fullname_end() + 1;
|
||||||
|
u64 fullname_len = end - buffer;
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < BUFF_SIZE - fullname_len; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = end[i];
|
||||||
|
end[i] = 0;
|
||||||
|
}
|
||||||
|
buffer_tail -= fullname_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_count(u64 count)
|
||||||
|
{
|
||||||
|
write(STDOUT, "count: ", 8);
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
char digit = (count % 10) + '0';
|
||||||
|
count /= 10;
|
||||||
|
write(STDOUT, &digit, 1);
|
||||||
|
}
|
||||||
|
write(STDOUT, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_name(char* accumulator)
|
||||||
|
{
|
||||||
|
char* start = find_second_word(buffer);
|
||||||
|
char* end = start;
|
||||||
|
for (; *end != ' '; end++);
|
||||||
|
if (!end)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; &start[i] < end; i++)
|
||||||
|
{
|
||||||
|
accumulator[i] = start[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int filedesc = openfile(argv[1]);
|
||||||
|
read(STDIN, name, sizeof(name)/sizeof(name[0]));
|
||||||
|
// fgets(name, sizeof(name)/sizeof(name[0]), stdin);
|
||||||
|
size_t count = 0;
|
||||||
|
char namebuff[NAME_SIZE] = {0, };
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!find_fullname_end())
|
||||||
|
{
|
||||||
|
fill_buffer(filedesc);
|
||||||
|
}
|
||||||
|
get_name(namebuff);
|
||||||
|
if (namecmp(namebuff, name))
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
pop_fullname();
|
||||||
|
} while (buffer_tail != buffer);
|
||||||
|
print_count(count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
467
coursework/main.s
Normal file
467
coursework/main.s
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
.file "main.c"
|
||||||
|
.intel_syntax noprefix
|
||||||
|
.text
|
||||||
|
.globl name
|
||||||
|
.bss
|
||||||
|
.align 32
|
||||||
|
.type name, @object
|
||||||
|
.size name, 64
|
||||||
|
name:
|
||||||
|
.zero 64
|
||||||
|
.globl buffer
|
||||||
|
.align 32
|
||||||
|
.type buffer, @object
|
||||||
|
.size buffer, 1024
|
||||||
|
buffer:
|
||||||
|
.zero 1024
|
||||||
|
.globl buffer_tail
|
||||||
|
.section .data.rel.local,"aw"
|
||||||
|
.align 8
|
||||||
|
.type buffer_tail, @object
|
||||||
|
.size buffer_tail, 8
|
||||||
|
buffer_tail:
|
||||||
|
.quad buffer
|
||||||
|
.globl iseof
|
||||||
|
.bss
|
||||||
|
.type iseof, @object
|
||||||
|
.size iseof, 1
|
||||||
|
iseof:
|
||||||
|
.zero 1
|
||||||
|
.text
|
||||||
|
.globl namecmp
|
||||||
|
.type namecmp, @function
|
||||||
|
namecmp:
|
||||||
|
.LFB6:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
mov QWORD PTR -8[rbp], rdi
|
||||||
|
mov QWORD PTR -16[rbp], rsi
|
||||||
|
jmp .L2
|
||||||
|
.L6:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx edx, BYTE PTR [rax]
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
cmp dl, al
|
||||||
|
je .L3
|
||||||
|
mov eax, 0
|
||||||
|
jmp .L4
|
||||||
|
.L3:
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
add QWORD PTR -16[rbp], 1
|
||||||
|
.L2:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
test al, al
|
||||||
|
je .L5
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
test al, al
|
||||||
|
jne .L6
|
||||||
|
.L5:
|
||||||
|
mov eax, 1
|
||||||
|
.L4:
|
||||||
|
pop rbp
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE6:
|
||||||
|
.size namecmp, .-namecmp
|
||||||
|
.section .rodata
|
||||||
|
.align 8
|
||||||
|
.LC0:
|
||||||
|
.string "Something went wrong while opening file\n"
|
||||||
|
.text
|
||||||
|
.globl openfile
|
||||||
|
.type openfile, @function
|
||||||
|
openfile:
|
||||||
|
.LFB7:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 32
|
||||||
|
mov QWORD PTR -24[rbp], rdi
|
||||||
|
mov rax, QWORD PTR -24[rbp]
|
||||||
|
mov esi, 0
|
||||||
|
mov rdi, rax
|
||||||
|
mov eax, 0
|
||||||
|
call open@PLT
|
||||||
|
mov DWORD PTR -4[rbp], eax
|
||||||
|
cmp DWORD PTR -4[rbp], 0
|
||||||
|
jns .L8
|
||||||
|
lea rax, .LC0[rip]
|
||||||
|
mov rdi, rax
|
||||||
|
call puts@PLT
|
||||||
|
mov edi, 1
|
||||||
|
call exit@PLT
|
||||||
|
.L8:
|
||||||
|
mov eax, DWORD PTR -4[rbp]
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE7:
|
||||||
|
.size openfile, .-openfile
|
||||||
|
.globl fill_buffer
|
||||||
|
.type fill_buffer, @function
|
||||||
|
fill_buffer:
|
||||||
|
.LFB8:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 32
|
||||||
|
mov DWORD PTR -20[rbp], edi
|
||||||
|
mov rdx, QWORD PTR buffer_tail[rip]
|
||||||
|
lea rax, buffer[rip]
|
||||||
|
sub rdx, rax
|
||||||
|
mov eax, 1024
|
||||||
|
sub rax, rdx
|
||||||
|
mov QWORD PTR -8[rbp], rax
|
||||||
|
mov rdx, QWORD PTR -8[rbp]
|
||||||
|
mov eax, DWORD PTR -20[rbp]
|
||||||
|
lea rcx, buffer[rip]
|
||||||
|
mov rsi, rcx
|
||||||
|
mov edi, eax
|
||||||
|
call read@PLT
|
||||||
|
mov QWORD PTR -16[rbp], rax
|
||||||
|
cmp QWORD PTR -16[rbp], 1023
|
||||||
|
ja .L11
|
||||||
|
mov BYTE PTR iseof[rip], 1
|
||||||
|
.L11:
|
||||||
|
lea rdx, buffer[rip]
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov QWORD PTR buffer_tail[rip], rax
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE8:
|
||||||
|
.size fill_buffer, .-fill_buffer
|
||||||
|
.globl find_second_word
|
||||||
|
.type find_second_word, @function
|
||||||
|
find_second_word:
|
||||||
|
.LFB9:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
mov QWORD PTR -8[rbp], rdi
|
||||||
|
jmp .L13
|
||||||
|
.L14:
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
.L13:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
cmp al, 32
|
||||||
|
jne .L14
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
pop rbp
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE9:
|
||||||
|
.size find_second_word, .-find_second_word
|
||||||
|
.globl find_fullname_end
|
||||||
|
.type find_fullname_end, @function
|
||||||
|
find_fullname_end:
|
||||||
|
.LFB10:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
lea rax, buffer[rip]
|
||||||
|
mov QWORD PTR -8[rbp], rax
|
||||||
|
jmp .L17
|
||||||
|
.L20:
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
.L17:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
cmp al, 10
|
||||||
|
jne .L18
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
test al, al
|
||||||
|
jne .L19
|
||||||
|
.L18:
|
||||||
|
lea rax, buffer[rip+1024]
|
||||||
|
cmp QWORD PTR -8[rbp], rax
|
||||||
|
jb .L20
|
||||||
|
.L19:
|
||||||
|
lea rax, buffer[rip+1024]
|
||||||
|
cmp QWORD PTR -8[rbp], rax
|
||||||
|
jne .L21
|
||||||
|
mov eax, 0
|
||||||
|
jmp .L22
|
||||||
|
.L21:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
.L22:
|
||||||
|
pop rbp
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE10:
|
||||||
|
.size find_fullname_end, .-find_fullname_end
|
||||||
|
.globl pop_fullname
|
||||||
|
.type pop_fullname, @function
|
||||||
|
pop_fullname:
|
||||||
|
.LFB11:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 32
|
||||||
|
mov eax, 0
|
||||||
|
call find_fullname_end
|
||||||
|
add rax, 1
|
||||||
|
mov QWORD PTR -16[rbp], rax
|
||||||
|
lea rdx, buffer[rip]
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
sub rax, rdx
|
||||||
|
mov QWORD PTR -24[rbp], rax
|
||||||
|
mov QWORD PTR -8[rbp], 0
|
||||||
|
jmp .L24
|
||||||
|
.L25:
|
||||||
|
mov rdx, QWORD PTR -16[rbp]
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
lea rcx, buffer[rip]
|
||||||
|
mov rdx, QWORD PTR -8[rbp]
|
||||||
|
add rdx, rcx
|
||||||
|
mov BYTE PTR [rdx], al
|
||||||
|
mov rdx, QWORD PTR -16[rbp]
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov BYTE PTR [rax], 0
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
.L24:
|
||||||
|
mov eax, 1024
|
||||||
|
sub rax, QWORD PTR -24[rbp]
|
||||||
|
cmp QWORD PTR -8[rbp], rax
|
||||||
|
jb .L25
|
||||||
|
mov rax, QWORD PTR buffer_tail[rip]
|
||||||
|
mov rdx, QWORD PTR -24[rbp]
|
||||||
|
neg rdx
|
||||||
|
add rax, rdx
|
||||||
|
mov QWORD PTR buffer_tail[rip], rax
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE11:
|
||||||
|
.size pop_fullname, .-pop_fullname
|
||||||
|
.section .rodata
|
||||||
|
.LC1:
|
||||||
|
.string "count: "
|
||||||
|
.LC2:
|
||||||
|
.string "\n"
|
||||||
|
.text
|
||||||
|
.globl print_count
|
||||||
|
.type print_count, @function
|
||||||
|
print_count:
|
||||||
|
.LFB12:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 32
|
||||||
|
mov QWORD PTR -24[rbp], rdi
|
||||||
|
mov edx, 8
|
||||||
|
lea rax, .LC1[rip]
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write@PLT
|
||||||
|
jmp .L27
|
||||||
|
.L28:
|
||||||
|
mov rcx, QWORD PTR -24[rbp]
|
||||||
|
movabs rdx, -3689348814741910323
|
||||||
|
mov rax, rcx
|
||||||
|
mul rdx
|
||||||
|
shr rdx, 3
|
||||||
|
mov rax, rdx
|
||||||
|
sal rax, 2
|
||||||
|
add rax, rdx
|
||||||
|
add rax, rax
|
||||||
|
sub rcx, rax
|
||||||
|
mov rdx, rcx
|
||||||
|
mov eax, edx
|
||||||
|
add eax, 48
|
||||||
|
mov BYTE PTR -1[rbp], al
|
||||||
|
mov rax, QWORD PTR -24[rbp]
|
||||||
|
movabs rdx, -3689348814741910323
|
||||||
|
mul rdx
|
||||||
|
mov rax, rdx
|
||||||
|
shr rax, 3
|
||||||
|
mov QWORD PTR -24[rbp], rax
|
||||||
|
lea rax, -1[rbp]
|
||||||
|
mov edx, 1
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write@PLT
|
||||||
|
.L27:
|
||||||
|
cmp QWORD PTR -24[rbp], 0
|
||||||
|
jne .L28
|
||||||
|
mov edx, 1
|
||||||
|
lea rax, .LC2[rip]
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 1
|
||||||
|
call write@PLT
|
||||||
|
nop
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE12:
|
||||||
|
.size print_count, .-print_count
|
||||||
|
.globl get_name
|
||||||
|
.type get_name, @function
|
||||||
|
get_name:
|
||||||
|
.LFB13:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 40
|
||||||
|
mov QWORD PTR -40[rbp], rdi
|
||||||
|
lea rax, buffer[rip]
|
||||||
|
mov rdi, rax
|
||||||
|
call find_second_word
|
||||||
|
mov QWORD PTR -24[rbp], rax
|
||||||
|
mov rax, QWORD PTR -24[rbp]
|
||||||
|
mov QWORD PTR -8[rbp], rax
|
||||||
|
jmp .L30
|
||||||
|
.L31:
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
.L30:
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
cmp al, 32
|
||||||
|
jne .L31
|
||||||
|
cmp QWORD PTR -8[rbp], 0
|
||||||
|
jne .L32
|
||||||
|
mov eax, -1
|
||||||
|
jmp .L33
|
||||||
|
.L32:
|
||||||
|
mov QWORD PTR -16[rbp], 0
|
||||||
|
jmp .L34
|
||||||
|
.L35:
|
||||||
|
mov rdx, QWORD PTR -24[rbp]
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
mov rcx, QWORD PTR -40[rbp]
|
||||||
|
mov rdx, QWORD PTR -16[rbp]
|
||||||
|
add rdx, rcx
|
||||||
|
movzx eax, BYTE PTR [rax]
|
||||||
|
mov BYTE PTR [rdx], al
|
||||||
|
add QWORD PTR -16[rbp], 1
|
||||||
|
.L34:
|
||||||
|
mov rdx, QWORD PTR -24[rbp]
|
||||||
|
mov rax, QWORD PTR -16[rbp]
|
||||||
|
add rax, rdx
|
||||||
|
cmp rax, QWORD PTR -8[rbp]
|
||||||
|
jb .L35
|
||||||
|
mov eax, 0
|
||||||
|
.L33:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE13:
|
||||||
|
.size get_name, .-get_name
|
||||||
|
.globl main
|
||||||
|
.type main, @function
|
||||||
|
main:
|
||||||
|
.LFB14:
|
||||||
|
.cfi_startproc
|
||||||
|
push rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
mov rbp, rsp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
sub rsp, 96
|
||||||
|
mov DWORD PTR -84[rbp], edi
|
||||||
|
mov QWORD PTR -96[rbp], rsi
|
||||||
|
mov rax, QWORD PTR -96[rbp]
|
||||||
|
add rax, 8
|
||||||
|
mov rax, QWORD PTR [rax]
|
||||||
|
mov rdi, rax
|
||||||
|
call openfile
|
||||||
|
mov DWORD PTR -12[rbp], eax
|
||||||
|
mov edx, 64
|
||||||
|
lea rax, name[rip]
|
||||||
|
mov rsi, rax
|
||||||
|
mov edi, 0
|
||||||
|
call read@PLT
|
||||||
|
mov QWORD PTR -8[rbp], 0
|
||||||
|
mov QWORD PTR -80[rbp], 0
|
||||||
|
mov QWORD PTR -72[rbp], 0
|
||||||
|
mov QWORD PTR -64[rbp], 0
|
||||||
|
mov QWORD PTR -56[rbp], 0
|
||||||
|
mov QWORD PTR -48[rbp], 0
|
||||||
|
mov QWORD PTR -40[rbp], 0
|
||||||
|
mov QWORD PTR -32[rbp], 0
|
||||||
|
mov QWORD PTR -24[rbp], 0
|
||||||
|
.L39:
|
||||||
|
mov eax, 0
|
||||||
|
call find_fullname_end
|
||||||
|
test rax, rax
|
||||||
|
jne .L37
|
||||||
|
mov eax, DWORD PTR -12[rbp]
|
||||||
|
mov edi, eax
|
||||||
|
call fill_buffer
|
||||||
|
.L37:
|
||||||
|
lea rax, -80[rbp]
|
||||||
|
mov rdi, rax
|
||||||
|
call get_name
|
||||||
|
lea rax, -80[rbp]
|
||||||
|
lea rdx, name[rip]
|
||||||
|
mov rsi, rdx
|
||||||
|
mov rdi, rax
|
||||||
|
call namecmp
|
||||||
|
test eax, eax
|
||||||
|
je .L38
|
||||||
|
add QWORD PTR -8[rbp], 1
|
||||||
|
.L38:
|
||||||
|
mov eax, 0
|
||||||
|
call pop_fullname
|
||||||
|
mov rdx, QWORD PTR buffer_tail[rip]
|
||||||
|
lea rax, buffer[rip]
|
||||||
|
cmp rdx, rax
|
||||||
|
jne .L39
|
||||||
|
mov rax, QWORD PTR -8[rbp]
|
||||||
|
mov rdi, rax
|
||||||
|
call print_count
|
||||||
|
mov eax, 0
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE14:
|
||||||
|
.size main, .-main
|
||||||
|
.ident "GCC: (Debian 14.2.0-6) 14.2.0"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
292
coursework/old/main.asm
Normal file
292
coursework/old/main.asm
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
global _start
|
||||||
|
|
||||||
|
%define STDIN 0
|
||||||
|
%define STDOUT 1
|
||||||
|
%define STDERR 2
|
||||||
|
%define RD_ONLY 00
|
||||||
|
|
||||||
|
%define FILE_BUF_SIZE 1024
|
||||||
|
|
||||||
|
section .data
|
||||||
|
buffer_tail_ptr dq file_buffer ; stores pointer to the end of the buffer for file
|
||||||
|
is_eof db 0 ; indicates if file ended
|
||||||
|
count dq 0 ; сколько имен нашлось
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
name resb 128
|
||||||
|
real_name_len resb 1
|
||||||
|
name_size equ $-name
|
||||||
|
|
||||||
|
file_descriptor resq 1
|
||||||
|
file_buffer resb FILE_BUF_SIZE
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
%macro PRINT_STR 1
|
||||||
|
jmp %%run ; we define data right in code. It's not good, but ok for prototype
|
||||||
|
%%string db %1
|
||||||
|
%%string_len equ $-%%string
|
||||||
|
%%run:
|
||||||
|
mov rax, 1
|
||||||
|
mov rdi, STDOUT
|
||||||
|
mov rsi, %%string
|
||||||
|
mov rdx, %%string_len
|
||||||
|
syscall
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro MPUSH 1-*
|
||||||
|
%rep %0
|
||||||
|
push %1
|
||||||
|
%rotate 1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro MPOP_R 1-*
|
||||||
|
%rotate -1
|
||||||
|
%rep %0
|
||||||
|
pop %1
|
||||||
|
%rotate -1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
is_alpha: ; dl - symbol in ascii
|
||||||
|
xor al, al
|
||||||
|
cmp dl, 'A'
|
||||||
|
jl .exit
|
||||||
|
cmp dl, 'z'
|
||||||
|
jg .exit
|
||||||
|
; dl < 'Z' or dl > 'a'
|
||||||
|
cmp dl, 'Z'
|
||||||
|
jl .true
|
||||||
|
cmp dl, 'a'
|
||||||
|
jg .true
|
||||||
|
jmp .exit
|
||||||
|
.true:
|
||||||
|
mov al, 1
|
||||||
|
.exit:
|
||||||
|
ret
|
||||||
|
|
||||||
|
fill_buf: ; read bytes from file to buffer
|
||||||
|
MPUSH rdi, rsi, rcx, r11, rdx
|
||||||
|
mov rdi, [buffer_tail_ptr]
|
||||||
|
call buffer_left
|
||||||
|
mov rdx, rax
|
||||||
|
mov rax, 0
|
||||||
|
mov rdi, [file_descriptor]
|
||||||
|
mov rsi, [buffer_tail_ptr]
|
||||||
|
; mov rdx, FILE_BUF_SIZE
|
||||||
|
syscall
|
||||||
|
cmp rax, 0
|
||||||
|
jl file_read_error
|
||||||
|
add [buffer_tail_ptr], rax
|
||||||
|
cmp rax, FILE_BUF_SIZE
|
||||||
|
jg .exit
|
||||||
|
mov byte [is_eof], 1
|
||||||
|
.exit:
|
||||||
|
MPOP_R rdi, rsi, rcx, r11, rdx
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_name: ; ask user for name he is searching for
|
||||||
|
MPUSH rax, rdi, rsi, rdx, rcx
|
||||||
|
mov rax, 0
|
||||||
|
mov rdi, STDIN
|
||||||
|
mov rsi, name
|
||||||
|
mov rdx, name_size
|
||||||
|
syscall ; returns number of read bytes
|
||||||
|
cmp rax, 0
|
||||||
|
jl read_error
|
||||||
|
test rax, rax
|
||||||
|
jz no_name_error ; if no bytes were read
|
||||||
|
mov [real_name_len], al
|
||||||
|
; if user didn't end output with CTRL+D, there will be one extra symbol
|
||||||
|
mov dl, [name + rax - 1]
|
||||||
|
call is_alpha ; check if last symbol is alpha
|
||||||
|
test al, al
|
||||||
|
jnz .exit
|
||||||
|
; if last symbol is \n or something simmilar, erase it
|
||||||
|
xor rdx, rdx
|
||||||
|
mov dl, byte [real_name_len]
|
||||||
|
mov byte [name + rdx - 1], 0 ; clear last char if non alpha
|
||||||
|
dec byte [real_name_len]
|
||||||
|
.exit:
|
||||||
|
MPOP_R rax, rdi, rsi, rdx, rcx
|
||||||
|
ret
|
||||||
|
|
||||||
|
are_names_equal: ; takes first fullname from buff and compares
|
||||||
|
MPUSH rcx, rsi, rdi
|
||||||
|
; jump to second word
|
||||||
|
mov rdi, file_buffer
|
||||||
|
mov rcx, FILE_BUF_SIZE
|
||||||
|
mov al, ' '
|
||||||
|
repne scasb ; Теперь мы указываем на символ второго слова
|
||||||
|
mov r8, rdi ; store for later
|
||||||
|
repne scasb ; Ищем второй пробел, чтобы определить границы второго слова
|
||||||
|
dec rdi ; Нашелся второй пробел. убавляем 1 чтобы указывать именно на него
|
||||||
|
sub rdi, r8 ; len
|
||||||
|
mov rax, rdi
|
||||||
|
cmp al, [real_name_len]
|
||||||
|
jnz .false ; if lenghts are different - already false
|
||||||
|
mov rdi, r8 ; return to pointer on second word
|
||||||
|
mov rsi, name
|
||||||
|
xor rcx, rcx
|
||||||
|
mov cl, [real_name_len]
|
||||||
|
repe cmpsb
|
||||||
|
jnz .false
|
||||||
|
.true:
|
||||||
|
mov rax, 1
|
||||||
|
jmp .exit
|
||||||
|
.false:
|
||||||
|
mov rax, 0
|
||||||
|
.exit:
|
||||||
|
MPOP_R rcx, rsi ,rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
buffer_left: ; counts free part of buffer
|
||||||
|
push rdi
|
||||||
|
mov rax, FILE_BUF_SIZE
|
||||||
|
sub rdi, file_buffer
|
||||||
|
sub rax, rdi
|
||||||
|
pop rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
pop_from_addr: ; frees buffer from one name until \n, takes 1 addr
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
MPUSH rdx, rax
|
||||||
|
sub rsp, 24
|
||||||
|
mov [rbp-24], rdi ; char* start
|
||||||
|
call buffer_left
|
||||||
|
mov [rbp-16], rax ; * count
|
||||||
|
mov QWORD [rbp-8], 0 ; i
|
||||||
|
;loop
|
||||||
|
.loop:
|
||||||
|
; read byte from start[i]
|
||||||
|
mov rdx, [rbp-24]
|
||||||
|
mov rax, [rbp-8]
|
||||||
|
add rax, rdx
|
||||||
|
mov al, [rax]
|
||||||
|
; place to buffer[i]
|
||||||
|
mov rdx, [rbp-8]
|
||||||
|
add rdx, file_buffer
|
||||||
|
mov [rdx], al
|
||||||
|
; move zero to read position
|
||||||
|
mov rdx, [rbp-24]
|
||||||
|
mov rax, [rbp-8]
|
||||||
|
add rax, rdx
|
||||||
|
mov byte [rax], 0
|
||||||
|
inc qword [rbp-8]
|
||||||
|
; .cond:
|
||||||
|
mov rax, [rbp-8]
|
||||||
|
cmp rax, [rbp-16]
|
||||||
|
jb .loop
|
||||||
|
; update buffer_tail_ptr
|
||||||
|
mov rax, [rbp-24]
|
||||||
|
sub rax, file_buffer
|
||||||
|
sub [buffer_tail_ptr], rax
|
||||||
|
add rsp, 24
|
||||||
|
MPOP_R rcx, rax
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
free_fullname:
|
||||||
|
MPUSH rcx, rdi, rax
|
||||||
|
mov rcx, FILE_BUF_SIZE
|
||||||
|
mov rdi, file_buffer
|
||||||
|
mov al, `\n`
|
||||||
|
repne scasb
|
||||||
|
call pop_from_addr
|
||||||
|
MPOP_R rcx, rdi, rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
_start:
|
||||||
|
; --parse command_line arguments
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
; --check if there is any args
|
||||||
|
mov rax, [rbp + 8]
|
||||||
|
cmp rax, 2
|
||||||
|
jl no_filepath
|
||||||
|
; --if argument specified, try to read path
|
||||||
|
mov rdi, [rbp + 8*3]
|
||||||
|
mov rax, 0x2 ; open file
|
||||||
|
mov rsi, RD_ONLY
|
||||||
|
xor rdx, rdx
|
||||||
|
syscall ; filepath already should be in rdi
|
||||||
|
mov [file_descriptor], rax
|
||||||
|
cmp rax, 0
|
||||||
|
jl file_open_error
|
||||||
|
; --asking user what name we are looking for
|
||||||
|
PRINT_STR `Input name you are looking for: `
|
||||||
|
call read_name
|
||||||
|
; -- find number of occurenses. HARDEST PART
|
||||||
|
.fill_buff_prefix:
|
||||||
|
call fill_buf
|
||||||
|
.name_cmp_loop:
|
||||||
|
mov rdi, name
|
||||||
|
call are_names_equal
|
||||||
|
test rax, rax
|
||||||
|
jz .no_increment
|
||||||
|
inc qword [count]
|
||||||
|
.no_increment:
|
||||||
|
call free_fullname
|
||||||
|
; iseof && buffer_tail_ptr == file_buffer
|
||||||
|
mov rax, [buffer_tail_ptr]
|
||||||
|
cmp rax, file_buffer
|
||||||
|
jne .name_cmp_loop
|
||||||
|
mov al, [is_eof]
|
||||||
|
test al, al
|
||||||
|
jz .fill_buff_prefix
|
||||||
|
;formatted output
|
||||||
|
mov rax, 1 ; write
|
||||||
|
mov rdi, STDOUT
|
||||||
|
mov rsi, name
|
||||||
|
mov rdx, [real_name_len]
|
||||||
|
syscall
|
||||||
|
PRINT_STR " ............... "
|
||||||
|
; printing number
|
||||||
|
mov rax, [count]
|
||||||
|
mov rbx, 10
|
||||||
|
xor rcx, rcx
|
||||||
|
.number_converting_loop:
|
||||||
|
xor rdx, rdx
|
||||||
|
div rbx
|
||||||
|
; push 1 byte to stack
|
||||||
|
add dl, '0' ; convert to ascii
|
||||||
|
dec rsp
|
||||||
|
mov [rsp], dl
|
||||||
|
inc rcx
|
||||||
|
test rax, rax
|
||||||
|
jnz .number_converting_loop
|
||||||
|
mov rax, 1
|
||||||
|
mov rdi, STDOUT
|
||||||
|
mov rsi, rsp
|
||||||
|
mov rdx, rcx
|
||||||
|
syscall
|
||||||
|
PRINT_STR `\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
read_error:
|
||||||
|
PRINT_STR `Error while reading the name\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
no_name_error:
|
||||||
|
PRINT_STR `No propper name given\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
file_open_error:
|
||||||
|
PRINT_STR `Failed to open the file\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
file_read_error:
|
||||||
|
PRINT_STR `Error while reading the file\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
no_filepath:
|
||||||
|
PRINT_STR `You haven't specified a file to read from\n`
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mov rax, 60
|
||||||
|
mov rdi, 0
|
||||||
|
syscall
|
||||||
|
|
||||||
Reference in New Issue
Block a user