alloc/free working (not merging)

This commit is contained in:
nub31
2025-02-03 22:31:23 +01:00
parent 958a301d18
commit 535444eb2a

View File

@@ -6,52 +6,120 @@ section .bss
section .text section .text
alloc: alloc:
add rdi, 16 ; add space for metadata add rdi, 16 ; reserve 16 bytes for metadata
mov rax, [free_list_head] ; load head of free list mov rsi, [free_list_head]
xor r8, r8 ; last block xor r8, r8
.loop: .loop:
test rax, rax ; end of list? test rsi, rsi ; allocate new block if end of list is reached
jz .new_block ; yes? allocate new block jz .new_block
cmp [rax], rdi ; does object fit in block and have space for metadata? mov rdx, [rsi]
jge .found_block ; yes? use this block cmp rdx, rdi ; is there enough space for allocation?
mov r8, rax ja .use_block ; yes? allocate
mov rax, [rax + 8] ; load next free block add rdx, 16
jb .loop ; no? go to next block cmp rdx, rdi ; no? is there enough space if we include metadata
.found_block: je .use_block ; if we include metadata, the sizes has to match exactly, or partial metadata will persist
sub qword [rax], rdi ; reduce the available size of the block mov r8, rsi ; r8 contains the node from the last iteration
cmp qword [rax], 0 ; no space left in block? mov rsi, [rsi + 8] ; next node
jg .done_remove_free_block ; no? do not remove block from free list jmp .loop
mov rsi, [rax + 8] ; yes? remove block from free list
test r8, r8 ; is current head of list?
jz .remove_free_head ; yes? remove head
mov [r8 + 8], rsi ; set prev.next to this.next
jmp .done_remove_free_block
.remove_free_head:
mov [free_list_head], rsi
.done_remove_free_block:
mov rsi, [rax] ; load size of block excluding the newly allocated object
lea rax, [rax + rsi + 16] ; address of allocated block
sub rdi, 16
mov [rax], rdi ; save size
mov rsi, [alloc_list_head] ; load head of allocated blocks
mov [rax + 8], rsi ; move head to be next item after this block
mov [alloc_list_head], rax ; set new head to this block
lea rax, [rax + 16] ; skip metadata for return value
ret
.new_block: .new_block:
push rdi push rdi
push r8 push r8
mov rdi, 4096 ; page size add rdi, 16
call sys_mmap ; allocate a page mov rsi, 4096
mov qword [rax], 4080 ; set size of block to block size - metadata call max
mov rsi, [free_list_head] push rax
mov qword [rax + 8], rsi ; move head to be the next item after this block mov rdi, rax
mov [free_list_head], rax ; set new head to this block call sys_mmap
pop rsi
sub rsi, 16
mov qword [rax], rsi ; update metadata to page size - metadata
push rax
mov rdi, rax
call insert_into_free
pop rsi
pop r8 pop r8
pop rdi pop rdi
jmp .found_block .use_block:
cmp [rsi], rdi ; check if the block will be empty after allocation
ja .unlink_done ; if not, do not unlink
test r8, r8 ; r8 is null if node is also head
jz .unlink_head
mov rdx, [rsi + 8] ; load next node
mov [r8 + 8], rdx ; link next node to last node's next
jmp .unlink_done
.unlink_head:
mov rdx, [free_list_head] ; load head
mov rdx, [rdx + 8] ; load head.next
mov [free_list_head], rdx ; mov head.next into head
.unlink_done:
sub [rsi], rdi ; reduce available space of block by the allocated space
mov rdx, [rsi] ; load the available space excluding the newly allocated space
lea rax, [rsi + rdx + 16] ; load the address of the newly allocated space
sub rdi, 16
mov [rax], rdi ; update metadata to allocation size - metadata
mov rdx, [alloc_list_head]
mov [rax + 8], rdx ; move head to nex item in this alloc
mov [alloc_list_head], rax ; update head to point to this node
lea rax, [rax + 16] ; skip past metadata for return value
ret
free: free:
lea rdi, [rdi - 16] ; adjust for metadata
mov rsi, [alloc_list_head]
xor r8, r8
.loop:
test rsi, rsi
jz .not_found
cmp rdi, rsi
je .found
mov r8, rsi
mov rsi, [rsi + 8] ; next node
jmp .loop
.not_found:
mov rax, 60
mov rdi, 1
syscall
.found:
test r8, r8 ; r8 is null if node is also head
jz .unlink_head
mov rdx, [rsi + 8] ; load next node
mov [r8 + 8], rdx ; link next node to last node's next
jmp .unlink_done
.unlink_head:
mov rdx, [alloc_list_head] ; load head
mov rdx, [rdx + 8] ; load head.next
mov [alloc_list_head], rdx ; mov head.next into head
.unlink_done:
mov rdi, rsi
call insert_into_free
ret
insert_into_free:
mov rsi, [free_list_head] ; load head
test rsi, rsi ; is list empty
jz .insert_head ; if empty, insert at head
cmp rdi, rsi ; is input smaller then head
jl .insert_head ; if smaller, insert at head
xor r8, r8 ; r9 will track the previous node
.loop:
test rsi, rsi
jz .insert_end ; if at end of list, insert at end
cmp rdi, [rsi + 8] ; compare input to next node
jg .next ; if larger, skip to next node
mov [rsi + 8], rdi ; if smaller, insert at this position
mov [rdi + 8], rdx
ret
.next:
mov r8, rsi ; update r8 to current node
mov rsi, [rsi + 8] ; update rsi to next node
jmp .loop
.insert_head:
mov rdx, [free_list_head]
mov [rdi + 8], rdx
mov [free_list_head], rdi
ret
.insert_end:
mov [r8 + 8], rdi ; update last node's next to point at rdi
ret ret
sys_mmap: sys_mmap:
@@ -81,3 +149,12 @@ sys_munmap:
mov rax, 60 mov rax, 60
mov rdi, 1 mov rdi, 1
syscall syscall
max:
cmp rdi, rsi
jae .left
mov rax, rsi
ret
.left:
mov rax, rdi
ret