diff --git a/lang/src/main.asm b/lang/src/main.asm index 0066521..b244aa9 100644 --- a/lang/src/main.asm +++ b/lang/src/main.asm @@ -7,6 +7,10 @@ section .data hello_msg_len equ $ - hello_msg die_msg db "panic occured!", 10 die_msg_len equ $ - die_msg + file_error_msg db "Could not open file: " + file_error_msg_len equ $ - file_error_msg + error_msg db "Error: " + error_msg_len equ $ - error_msg section .text global _start @@ -21,10 +25,15 @@ _start: mov rax, [rsp] ; argc cmp rax, 1 jle .no_filename ; if argc <= 1, no filename provided + ; get argv[1] + mov rax, [rsp + 16] ; argv[1] + + ; open file for reading + mov rdx, rax ; filename pointer + call fopen_read mov rax, 42 ret - .no_filename: call die @@ -38,6 +47,13 @@ die: syscall ret ; should never reach here +;; ============================== +;; Helper functions +;; ============================== + +;; Writes a string to stderr: +;; rdx: pointer to string +;; rcx: length of string eprint_str: ; print string-length pair to stderr ; str pointer in rdx ; length in rcx @@ -47,5 +63,82 @@ eprint_str: ; print string-length pair to stderr mov rdx, rcx ; len: length syscall ret + +;; calculates length of null-terminated string +;; rdx: pointer to string +strlen: + xor rax, rax ; length counter +.strlen_loop: + cmp byte [rdx + rax], 0 + je .strlen_done + inc rax + jmp .strlen_loop +.strlen_done: + ret + +;; Copy bytes from one memory location to another +;; rdx: destination pointer +;; rcx: source pointer +;; r8: number of bytes to copy +memcpy: + xor r10, r10 +.memcpy_loop_byte: + cmp r10, r8 + jge .memcpy_done + mov al, [rcx + r10] + mov [rdx + r10], al + inc r10 + jmp .memcpy_loop_byte +.memcpy_done: + ret + +;; Opens file for reading: + ;; rdx: pointer to filename (null-terminated) +fopen_read: + mov rax, 2 ; syscall: open + mov rdi, rdx ; filename + mov rsi, 0 ; flags: O_RDONLY + mov rdx, 0 ; mode + syscall + cmp rax, 0 + jl .file_error + ret ;fd in rax +.file_error: + ; allocate stack space for error message + mov rdx, rdi ; filename is in rdi + call strlen ; get length of filename + mov r9, rax + mov rsi, r9 + add rsi, file_error_msg_len ; add length of error message prefix + add rsi, 1 ; for new line + ; align to 16 bytes + add rsi, 15 + and rsi, -16 + sub rsp, rsi ; alloca + push rsi ; save length for dealloca + ; copy file_error_msg + lea rdx, [rsp + 8] + mov rcx, file_error_msg + mov r8, file_error_msg_len + call memcpy + ; copy filename + lea rdx, [rsp + 8 + file_error_msg_len] + mov rcx, rdi + mov r8, r9 + call memcpy + ; trailing newline + lea rdx, [rsp + 8 + file_error_msg_len + r9] + mov byte [rdx], 10 + ; print error message + lea rdx, [rsp + 8] + mov rcx, r9 + add rcx, file_error_msg_len + add rcx, 1 + call eprint_str + pop rsi + add rsp, rsi ; dealloca + ret + +