1 Commits

Author SHA1 Message Date
9cf6ecc535 feat: done first task 2024-12-10 18:06:59 +03:00

292
coursework/old/main.asm Normal file
View 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