From 9cf6ecc535f80b290023f8378945abfa968075ad Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Tue, 10 Dec 2024 18:06:59 +0300 Subject: [PATCH] feat: done first task --- coursework/old/main.asm | 292 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 coursework/old/main.asm diff --git a/coursework/old/main.asm b/coursework/old/main.asm new file mode 100644 index 0000000..26dbad5 --- /dev/null +++ b/coursework/old/main.asm @@ -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 +