.intel_syntax noprefix .equ SYS_MMAP, 9 .equ SYS_MUNMAP, 11 .text .globl nub_strlen # func nub_strlen(string: cstring): u64 nub_strlen: test rdi, rdi jz null_string xor rax, rax strlen_loop: cmp byte ptr [rdi + rax], 0 je strlen_exit inc rax jmp strlen_loop null_string: xor rax, rax strlen_exit: ret .text .globl nub_cstring_to_string # func nub_cstring_to_string(string: cstring): []u8 nub_cstring_to_string: push rbx push r12 push r13 mov rbx, rdi # Save original pointer call nub_strlen mov r12, rax # r12 = string length # Calculate total space needed: 8 bytes (length) + string length mov r13, r12 add r13, 8 # r13 = total bytes needed # Round up to page size (4096 bytes) for mmap add r13, 4095 # Add page_size - 1 and r13, -4096 # Align to page boundary mov rax, SYS_MMAP xor rdi, rdi # addr = 0 (let kernel choose) mov rsi, r13 # length = aligned size mov rdx, 3 # prot = PROT_READ | PROT_WRITE mov r10, 34 # flags = MAP_PRIVATE | MAP_ANONYMOUS (0x22) mov r8, -1 # fd = -1 xor r9, r9 # offset = 0 syscall # Check if mmap failed cmp rax, -1 je mmap_failed mov r13, rax # r13 = pointer to mapped memory # Store length at beginning of mapped memory mov [r13], r12 # Store string length # Copy string data if not empty test r12, r12 # Check if length is 0 jz copy_done lea rdi, [r13 + 8] mov rsi, rbx mov rcx, r12 call nub_memcpy copy_done: mov rax, r13 jmp function_exit mmap_failed: xor rax, rax function_exit: pop r13 pop r12 pop rbx ret .text .globl nub_string_free # func nub_string_free(string: []u8): void nub_string_free: test rdi, rdi jz free_exit mov rsi, [rdi] add rsi, 8 # Round up to page size add rsi, 4095 and rsi, -4096 mov rax, SYS_MUNMAP syscall free_exit: ret