diff --git a/lang/src/lib.asm b/lang/src/lib.asm index 2637de6..3ce3379 100644 --- a/lang/src/lib.asm +++ b/lang/src/lib.asm @@ -43,8 +43,8 @@ panic: ;; Abort the program with a default panic message oom: - mov rcx, oom_msg - mov rdx, oom_msg_len + mov rdi, oom_msg + mov rsi, oom_msg_len call eprint_str ; exit with error code 1 mov rax, 60 ; syscall: exit @@ -52,28 +52,28 @@ oom: syscall ;; abort the program -;; rcx: status code +;; rdi: status code exit: mov rax, 60 ; syscall: exit - mov rdi, rcx syscall ;; Writes a string to stderr: -;; rcx: pointer to string -;; rdx: length of string +;; rdi: pointer to string +;; rsi: length of string eprint_str: mov rax, 1 ; syscall: write mov rdi, 2 ; fd: stderr - mov rsi, rcx ; buf: str + mov rdx, rsi ; len: length + mov rsi, rdi ; buf: str syscall ret ;; calculates length of null-terminated string -;; rcx: pointer to string +;; rdi: pointer to string strlen: xor rax, rax ; length counter .strlen_loop: - cmp byte [rcx + rax], 0 + cmp byte [rdi + rax], 0 je .strlen_done inc rax jmp .strlen_loop @@ -81,109 +81,110 @@ strlen: ret ;; Checks two byte slices for equality -;; rcx: pointer to first slice -;; rdx: length of first slice -;; r8: pointer to second slice -;; r9: length of second slice +;; rdi: pointer to first slice +;; rsi: length of first slice +;; rdx: pointer to second slice +;; rcx: length of second slice ;; returns: 1 if equal, 0 if not equal +;; fn streq(a: &[u8], b: &[u8]) -> bool streq: - cmp rdx, r9 - jne .not_equal ; lengths differ - - xor r10, r10 ; index = 0 -.loop: - cmp r10, rdx - jge .equal ; done all bytes - - mov al, [rcx + r10] ; char from a - mov bl, [r8 + r10] ; char from b - cmp al, bl - jne .not_equal ; chars differ - - inc r10 + ; if a.len() == b.len() { + cmp rsi, rcx + jne .false + ; for i in 0..a.len() { + xor r8, r8 +.loop + cmp r8, rsi + jge .true + ; if a[i] != b[i] { + mov al, [rdi + r8] + mov cl, [rdx + r8] + cmp al, cl + ; return false; + jne .false + ; } + inc r8 jmp .loop -.equal: - mov rax, 1 ; equal + ; } + ; return true; +.true: + mov rax, 1 ret -.not_equal: - xor rax, rax ; not equal + ; } else { + ; return false; +.false: + xor rax, rax ret - + ; } ;; Compares two byte slices -;; rcx: pointer to first slice -;; rdx: length of first slice -;; r8: pointer to second slice -;; r9: length of second slice -; returns: -1, 0, or 1 in rax +;; rdi: pointer to first slice +;; rsi: length of first slice +;; rdx: pointer to second slice +;; rcx: length of second slice + ;; returns: -1, 0, or 1 in rax + ;; fn strcmp(a: &[u8], b: &[u8]) -> Ordering strcmp: - xor rax, rax ; result = 0 (assume equal) - test rdx, rdx - jz .check_empty_b ; if len a == 0 - test r9, r9 - jz .check_empty_a ; if len b == 0 - - mov r10, rdx ; min(len a, len b) in r10 - cmp r9, rdx - cmovb r10, r9 - - xor r11, r11 ; index = 0 + ; let min_len = min(a.len(), b.len()); + mov rax, rsi + cmp rsi, rcx + cmovg rax, rcx + ; for i in 0..min_len { + xor r8, r8 .loop: - cmp r11, r10 - jge .after_loop ; done min(len a, len b) bytes - - mov al, [rcx + r11] ; char from a - mov bl, [r8 + r11] ; char from b - cmp al, bl - jb .less ; if al < bl: return -1 - ja .greater ; if al > bl: return 1 - - inc r11 + cmp r8, rax + jge .length_check + mov r9l, [rdi + r8] + mov r10l, [rdx + r8] + ; if a[i] < b[i] { + cmp r9l, r10l + ; return Ordering::Less; + jb .less + ; } else if a[i] > b[i] { + ; return Ordering::Greater; + ja .greater + ; } + inc r8 jmp .loop - -.after_loop: - cmp rdx, r9 - je .equal ; lengths equal, strings equal - jb .less ; a shorter than b - ja .greater ; a longer than b - -.equal: - xor rax, rax ; 0 + ; } + ; if a.len() < b.len() { +.length_check: + cmp rsi, rcx + ; return Ordering::Less; + jb .less + ; } else if a.len() > b.len() { + ; return Ordering::Greater; + ja .greater + ; } else { + ; return Ordering::Equal; + xor rax, rax ret - + ; } .less: mov rax, -1 ret - .greater: mov rax, 1 ret -.check_empty_a: - test rdx, rdx - jz .equal ; both empty - jmp .greater ; a not empty, b empty - -.check_empty_b: - test r9, r9 - jz .equal ; both empty - jmp .less ; b not empty, a empty - - ;; Copy bytes from one memory location to another -;; rcx: destination pointer -;; rdx: source pointer -;; r8: number of bytes to copy +;; rdi: destination pointer +;; rsi: source pointer +;; rdx: number of bytes to copy +;; fn memcpy(dest: *mut u8, src: *const u8, n: usize) memcpy: - xor r10, r10 -.memcpy_loop_byte: - cmp r10, r8 - jge .memcpy_done - mov al, [rdx + r10] - mov [rcx + r10], al - inc r10 - jmp .memcpy_loop_byte -.memcpy_done: + ; for i in 0..n { + xor r8, r8 +.loop: + cmp r8, rdx + jge .done + ; dest[i] = src[i]; + mov al, [rsi + r8] + mov [rdi + r8], al + inc r8 + jmp .loop + ; } +.done: ret section .rdata @@ -198,16 +199,16 @@ section .rdata section .text ;; Converts an error code to a str (pointer, length) pair -;; rcx: error code +;; rdi: error code ;; Returns: ;; rax: pointer to string ;; rdx: length of string error_to_str: - cmp rcx, -21 + cmp rdi, -21 je .e_is_dir - cmp rcx, -5 + cmp rdi, -5 je .e_io - cmp rcx, -9 + cmp rdi, -9 je .e_bad_fd ; unknown error @@ -227,48 +228,25 @@ error_to_str: mov rdx, e_bad_fd_len ret -;; rcx: error code +;; rdi: error code +;; fn eprint_error(err_code: isize) eprint_error: - ; prologue - push rsi - - ; get error string - call error_to_str - mov r12, rax ; r12 = pointer to error string - mov r13, rdx ; r13 = length of error string - mov rsi, r13 - add rsi, error_msg_len - add rsi, 1 - add rsi, 15 - and rsi, -16 ; align up to 16 - sub rsp, rsi ; allocate buffer - push rsi ; save allocation size - ; copy error_msg - lea rcx, [rsp + 8] - mov rdx, error_msg - mov r8, error_msg_len - call memcpy - ; copy error string - lea rcx, [rsp + 8 + error_msg_len] - mov rdx, r12 - mov r8, r13 - call memcpy - ; trailing newline - lea rdx, [rsp + 8 + error_msg_len + r13] - mov byte [rdx], 10 - ; print error message - lea rcx, [rsp + 8] - mov rdx, error_msg_len - add rdx, r13 - add rdx, 1 ; include newline + ; let err_code = err_code; + push rdi + ; eprint_str(ERROR_STR, ERROR_STR.len()); + mov rdi, error_msg + mov rsi, error_msg_len + call eprint_str + ; let (err, len) = error_to_str(err_code); + pop rdi + call error_to_str + ; eprint_str(err, len); + mov rdi, rax + mov rsi, rdx call eprint_str - pop rsi - add rsp, rsi ; dealloc - - ; epilogue - pop rsi ret + ;; Allocates n pages of memory ;; rcx: number of pages ;; Returns: @@ -292,27 +270,36 @@ alloc_pages: call oom ;; Returns 1 if cl is an ASCII alphabetic character, 0 otherwise -;; cl: byte to check +;; rdi: byte to check +;; fn is_alpha(c: u8) -> bool is_alpha: - cmp cl, 'A' - jb .not_alpha - cmp cl, 'Z' - jbe .is_alpha_ret - cmp cl, 'a' - jb .not_alpha - cmp cl, 'z' - jbe .is_alpha_ret -.is_alpha_ret: + ; if ('A' <= c + cmp dil, 'A' + jb .false + ; && c <= 'Z') + cmp dil, 'Z' + jbe .true + ; || ('a' <= c + cmp dil, 'a' + jb .false + ; && c <= 'z') { + cmp dil, 'z' + jbe .true + ; return true; +.true: mov rax, 1 ret -.not_alpha: + ; } else { + ; return false; +.false: xor rax, rax ret +;; check if dil is numeric (decimal) is_numeric: - cmp cl, '0' + cmp dil, '0' jb .not_numeric - cmp cl, '9' + cmp dil, '9' jbe .is_numeric_ret .is_numeric_ret: mov rax, 1 @@ -321,13 +308,13 @@ is_numeric: xor rax, rax ret -;; cl: byte to check +;; dil: byte to check is_id_continue: call is_alpha - cmp rax, 1 + test rax, rax je .is_id_continue_ret call is_numeric - cmp rax, 1 + test rax, rax je .is_id_continue_ret cmp cl, '_' je .is_id_continue_ret @@ -337,10 +324,10 @@ is_id_continue: mov rax, 1 ret -;; cl: byte to check +;; dil: byte to check is_id_start: call is_alpha - cmp rax, 1 + test rax, rax je .is_ret cmp cl, '_' je .is_ret