105 lines
2.6 KiB
Plaintext
105 lines
2.6 KiB
Plaintext
; linux x86_64
|
|
|
|
struc block
|
|
free: resb 1 ; whether or not this block is free
|
|
size: resb 2 ; size of the chunk of memory
|
|
next: resb 8 ; the next chunk after this one
|
|
mem:
|
|
endstruc
|
|
|
|
section .data
|
|
hStart: dq 0 ; the beginning of our heap space
|
|
break: dq 0 ; the current end of our heap space
|
|
|
|
|
|
section .text
|
|
|
|
Allocate:
|
|
|
|
push rdi ; save the size argument
|
|
|
|
cmp qword [break], 0 ; if breakpoint is zero this
|
|
je firstAlloc ; is the first call to allocate
|
|
|
|
mov rdi, qword [hStart] ; else address of heap start
|
|
|
|
findBlock: ; look for a suitable block of memory
|
|
|
|
cmp byte [rdi + free], 2
|
|
je newBlock ; end of heap reached, create new block
|
|
|
|
cmp byte [rdi + free], 0
|
|
je skipBlock ; this block taken
|
|
|
|
; this block is free, make
|
|
; sure it's big enough
|
|
mov bx, word [rdi + size]
|
|
mov rcx, qword [rsp] ; compare against our size arg
|
|
cmp cx, bx
|
|
jg skipBlock ; keep looking if not big enough
|
|
|
|
mov byte [rdi + free], 0 ; else mark as taken
|
|
add rdi, mem
|
|
add rsp, 8 ; discard size arg, we didn't need it
|
|
mov rax, rdi ; return pointer to this block
|
|
ret
|
|
|
|
skipBlock:
|
|
mov rsi, qword [rdi + next] ; load next
|
|
mov rdi, rsi ' block address
|
|
jmp findBlock
|
|
|
|
newBlock:
|
|
mov rax, rdi
|
|
add rdi, 1024
|
|
cmp rdi, qword [break]
|
|
jl initAndAllocate
|
|
push rax
|
|
mov rdi, qword [break] ; if we are getting low on
|
|
add rdi, 4096 ; heap space, we ask OS for
|
|
mov rax, 12 ; more memory with brk syscall
|
|
syscall
|
|
cmp rax, qword [break] ; if breakpoint has not increased,
|
|
je allocFail ; then memory could not be allocated
|
|
mov qword [break], rax
|
|
pop rax
|
|
jmp initAndAllocate
|
|
|
|
|
|
firstAlloc: ; extra work has to be done on first
|
|
mov rax, 12 ; call to this subroutine
|
|
mov rdi, 0
|
|
syscall
|
|
mov qword [hStart], rax ; init heap start
|
|
add rax, 4096
|
|
mov rdi, rax
|
|
mov rax, 12 ; get heap memory with sys brk
|
|
syscall
|
|
cmp rax, qword [hStart]
|
|
je allocFail
|
|
mov qword [break], rax
|
|
mov rax, qword [hStart]
|
|
|
|
initAndAllocate:
|
|
mov byte [rax + free], 0 ; mark block free
|
|
pop rdi ; pop size arg off stack
|
|
mov word [rax + size], di ; mark it's size
|
|
lea rsi, [rax + mem + rdi]
|
|
mov byte [rsi + free], 2 ; mark heap end block
|
|
mov qword [rax + next], rsi ; mark next block
|
|
add rax, mem ; return pointer to block's memory space
|
|
ret
|
|
|
|
allocFail: ; exit(1) when allocation fails
|
|
mov rax, 60
|
|
mov rdi, 1
|
|
syscall
|
|
ret
|
|
|
|
; free this block so it can be
|
|
; reused in a subsequent call to allocate
|
|
Release:
|
|
sub rdi, mem
|
|
mov byte [rdi + free], 1
|
|
ret
|