Compare commits
1 Commits
34ed7f9fcc
...
labs/cours
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cf6ecc535 |
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