From 69bd77c8c0b8ea2f72476534e27e7f0dd6d2e19c Mon Sep 17 00:00:00 2001 From: janis Date: Mon, 20 Oct 2025 16:35:00 +0200 Subject: [PATCH] strchr, memswap, blob vec --- lang/src/lib.asm | 51 +++++++++---- lang/src/vec.asm | 182 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 15 deletions(-) create mode 100644 lang/src/vec.asm diff --git a/lang/src/lib.asm b/lang/src/lib.asm index f310155..b5fef7d 100644 --- a/lang/src/lib.asm +++ b/lang/src/lib.asm @@ -14,8 +14,10 @@ global oom global panic global strlen global strcmp +global strchr global streq global memcpy +global memswap global eprint_str global exit global error_to_str @@ -33,8 +35,8 @@ global is_id_start ;; Abort the program with a default panic message panic: - mov rcx, panic_msg - mov rdx, panic_msg_len + mov rdi, panic_msg + mov rsi, panic_msg_len call eprint_str ; exit with error code 1 mov rax, 60 ; syscall: exit @@ -187,6 +189,32 @@ memcpy: .done: ret + +;; Swap bytes between two memory locations +;; rdi: pointer to first memory location +;; rsi: pointer to second memory location +;; rdx: number of bytes to swap +;; fn memswap(a: *mut u8, b: *mut u8, n: usize) +memswap: + ; for i in 0..n { + xor r8, r8 +.loop: + cmp r8, rdx + jge .done + ; let temp = a[i]; + mov al, [rdi + r8] + ; a[i] = b[i]; + mov cl, [rsi + r8] + mov [rdi + r8], cl + ; b[i] = temp; + mov [rsi + r8], al + inc r8 + jmp .loop + ; } +.done: + ret + + ;; Returns a pointer to the first occurrence of c in s, or null if not found ;; rdi: pointer to byte slice ;; rsi: length of byte slice @@ -223,9 +251,6 @@ strchr: mov rdx, rsi sub rdx, r8 ret - - - section .rdata e_is_dir db "Is a directory", 10 @@ -286,26 +311,22 @@ eprint_error: call eprint_str ret - -;; Allocates n pages of memory -;; rcx: number of pages -;; Returns: -;; rax: pointer to allocated memory -alloc_pages: +;; rdi: number of bytes to allocate +;; fn allocate(bytes: usize) -> *mut u8 +allocate: mov rax, 9 ; syscall: mmap + mov rsi, rdi ; length: number of bytes xor rdi, rdi ; addr: NULL - mov rsi, rcx ; length: number of pages - shl rsi, 12 ; length in bytes (page size = 4096) mov rdx, 3 ; prot: PROT_READ | PROT_WRITE mov r10, 34 ; flags: MAP_PRIVATE | MAP_ANONYMOUS mov r8, -1 ; fd: -1 xor r9, r9 ; offset: 0 syscall - cmp rax, -4095 ; check for error + cmp rax, -1 ; check for error jae .alloc_error ret .alloc_error: - mov rcx, rax ; error code + mov rdi, rax call eprint_error call oom diff --git a/lang/src/vec.asm b/lang/src/vec.asm new file mode 100644 index 0000000..bf0a272 --- /dev/null +++ b/lang/src/vec.asm @@ -0,0 +1,182 @@ +section .rdata + INIT_CAPACITY equ 4096 + +section .text +extern memcpy +extern memswap +extern oom +extern panic +extern eprint_str +extern allocate + +global vec_init +global vec_push +global vec_pop +global vec_swap +global vec_remove +global vec_get +global vec_free + + +;; Byte vector structure +;; struct Vec { +;; data: *mut u8, +;; len: usize, +;; capacity: usize, +;; } + + +;; Initialize a new vector +;; rdi: pointer to Vec struct +;; fn vec_init(vec: *mut Vec) +vec_init: + push rdi + ; (*vec).data = allocate(INIT_CAPACITY); + mov rdi, INIT_CAPACITY + call allocate + pop r15 + mov [r15], rax + ; (*vec).len = 0; + mov qword [r15 + 8], 0 + ; (*vec).capacity = INIT_CAPACITY; + mov qword [r15 + 16], INIT_CAPACITY + ret + +;; rdi: pointer to Vec struct +;; rsi: pointer to data to push +;; rdx: size of data to push +;; fn vec_push(vec: *mut Vec, data: &[u8]) +vec_push: + ; let vec, ptr, size; + sub rsp, 24 + mov [rsp], rdi ; save vec + mov [rsp + 8], rsi ; save data ptr + mov [rsp + 16], rdx ; save data size + ; vec_try_grow(vec, size); + mov rsi, rdx + call vec_try_grow + ; memcpy(&vec.data[vec.len], data, size); + mov rax, [rsp] ; vec + mov rdi, [rax] ; vec.data + add rdi, [rax + 8] ; vec.data + vec.len + mov rsi, [rsp + 8] ; data ptr + mov rdx, [rsp + 16] ; data size + call memcpy + ; vec.len += size; + mov rax, [rsp] ; vec + mov rbx, [rsp + 16] ; size + add [rax + 8], rbx + add rsp, 24 + ret + + +;; rdi: pointer to Vec struct +;; rsi: size of data to pop +;; fn vec_pop(vec: *mut Vec, size: usize) +vec_pop: + mov rax, [rdi + 8] ; len + cmp rax, rsi + jl .underflow + sub rax, rsi + mov [rdi + 8], rax + ret +.underflow: + call panic + ret + + +;; rdi: pointer to Vec struct +;; rsi: index a +;; rdx: index b +;; rcx: step size +;; fn vec_swap(vec: *mut Vec, a: usize, b: usize, step: usize) +vec_swap: + sub rsp, 32 + mov [rsp], rdi + mov [rsp + 8], rcx + ; let a = a * step; + imul rsi, rcx + mov [rsp + 16], rax + ; let b = b * step; + imul rdx, rcx + mov [rsp + 24], rbx + + ; let max_index = max(a, b); + mov rbx, rsi + cmp rbx, rdx + cmovl rbx, rdx + ; if (max_index >= vec.len) panic(); + mov rax, [rdi + 8] ; len + cmp rbx, rax + jge .panic + ; // a and b must not overlap + lea rdi, [rdi] ; vec.data + mov rsi, rdi + add rdi [rsp + 16] ; data + a + add rsi, [rsp + 24] ; data + b + mov rcx, [rsp + 8] ; step + call memswap + add rsp, 32 + ret + + +;; rdi: pointer to Vec struct +;; rsi: index +;; rdx: step size + ;; fn vec_remove(vec: *mut Vec, index: usize, step: usize) +vec_remove: + ; if (index * step >= vec.len) panic(); + ; if (vec.len - step == index * step { + ; vec.len -= step; + ; } else { + ; vec_swap(vec, index, vec.len / step - 1, step); + ; } + + + + + +;; rdi: pointer to Vec struct +;; rsi: push size +;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool +vec_try_grow: + mov rax, [rdi + 16] ; capacity + mov rbx, [rdi + 8] ; len + add rbx, rsi + cmp rbx, rax + jg .grow + xor rax, rax + ret +.grow: + ; let vec; + ; let new_capacity; + sub rsp, 16 + mov [rsp], rdi + ; new_capacity = max(capacity * 2, len + push_size) + mov rcx, [rdi + 16] ; capacity + shl rcx, 1 ; capacity * 2 + cmp rcx, rbx + cmovl rcx, rbx ; rcx = new_capacity + mov [rsp + 8], rcx + ; new_data = allocate(new_capacity); + mov rdi, rcx + call allocate + mov rdi, [rsp] + ; memcpy(new_data, old_data, len); + mov rbx, [rdi + 8] ; len + mov rsi, [rdi] ; old_data + mov rdi, rax ; new_data + mov rdx, rbx ; len + call memcpy + ; free(old_data) // TODO + ; update vec + mov rdi, [rsp] + mov [rdi], rax ; data = new_data + mov rcx, [rsp + 8] + mov [rdi + 16], rcx ; capacity = new_capacity + add rsp, 16 + xor rax, rax + ret + + +