243 lines
3.3 KiB
NASM
243 lines
3.3 KiB
NASM
|
# Copyright (c) 2024 Freya Murphy
|
||
|
|
||
|
.data
|
||
|
.align 2
|
||
|
|
||
|
heap_start:
|
||
|
.space 4
|
||
|
heap_len:
|
||
|
.space 4
|
||
|
heap_free:
|
||
|
.space 4
|
||
|
heap_ptr:
|
||
|
.space 4
|
||
|
|
||
|
null:
|
||
|
.space 4
|
||
|
|
||
|
.text
|
||
|
.align 2
|
||
|
.globl main
|
||
|
|
||
|
# init the heap
|
||
|
heap_init:
|
||
|
# sbrk(0)
|
||
|
li $v0, 9
|
||
|
li $a0, 0
|
||
|
syscall
|
||
|
sw $v0, heap_start
|
||
|
sw $v1, heap_len
|
||
|
|
||
|
# heap is empty, ptr at start
|
||
|
sw $v0, heap_ptr
|
||
|
# heap is empty, size = len
|
||
|
sw $v1, heap_free
|
||
|
|
||
|
jr $ra
|
||
|
|
||
|
|
||
|
|
||
|
# $a0 : amount of bytes to increase
|
||
|
heap_increase:
|
||
|
# t0 : OLD heap len + 1
|
||
|
# t1 : heap ptr
|
||
|
# t2 : heap end
|
||
|
# t2 : heap free
|
||
|
# t3 : a0
|
||
|
|
||
|
# save current length
|
||
|
lw $t0, heap_len
|
||
|
|
||
|
# save a0
|
||
|
move $t3, $a0
|
||
|
|
||
|
# sbrk(amt)
|
||
|
li $v0, 9
|
||
|
syscall
|
||
|
# sbrk(0)
|
||
|
li $v0, 9
|
||
|
li $a0, 0
|
||
|
syscall
|
||
|
sw $v0, heap_start
|
||
|
sw $v1, heap_len
|
||
|
|
||
|
lw $t1, heap_ptr # heap ptr
|
||
|
add $t2, $v0, $v1 # heap end
|
||
|
sub $t3, $t2, $t1 # heap free
|
||
|
sw $t3, heap_free
|
||
|
|
||
|
# set return code to 1 if fail to allocate
|
||
|
# i.e. $v1 = $t0 or ($v1 < $t0 + 1)
|
||
|
# i.e. heap size hasen't changed
|
||
|
addi $t0, $t0, 1
|
||
|
slt $v0, $v1, $t0
|
||
|
jr $ra
|
||
|
|
||
|
|
||
|
|
||
|
# $a0 : amount of bytes to allocate
|
||
|
malloc:
|
||
|
# t0 : heap free + 1
|
||
|
# t1 : if enough mem is free
|
||
|
# t2 : alloc size [(a0 align 4) + 4096 + 4]
|
||
|
# t3 : temp for heap_ptr
|
||
|
# t7 : alloc amt (a0 align 4) + 4
|
||
|
# t8 : temp for modulo
|
||
|
|
||
|
# save $a0
|
||
|
move $t7, $a0
|
||
|
addi $t7, $t7, 4 # add 4 bytes to save INTERAL ptr size
|
||
|
|
||
|
# align $t7 by 4
|
||
|
# allows us to use lw and sw in realloc
|
||
|
li $t8, 4
|
||
|
div $t8, $t7, $t8
|
||
|
mfhi $t8
|
||
|
beq $t8, $zero, malloc_aligned
|
||
|
addi $t7, $t7, 4
|
||
|
sub $t7, $t7, $t8
|
||
|
|
||
|
malloc_aligned:
|
||
|
# check if we have enough memory free
|
||
|
lw $t0, heap_free
|
||
|
addi $t0, $t0, 1
|
||
|
slt $t1, $t7, $t0
|
||
|
bne $t1, $zero, malloc_hasmem
|
||
|
|
||
|
# set needed mem to alloc
|
||
|
# page size + alloc request
|
||
|
|
||
|
# save $ra and $t7
|
||
|
addi $sp, $sp, -8
|
||
|
sw $ra, 0($sp)
|
||
|
sw $t7, 4($sp)
|
||
|
|
||
|
li $t2, 4096
|
||
|
add $t2, $t2, $t7
|
||
|
move $a0, $t2
|
||
|
jal heap_increase
|
||
|
|
||
|
# pop $ra and $t7
|
||
|
lw $ra, 0($sp)
|
||
|
lw $t7, 4($sp)
|
||
|
addi $sp, $sp, 8
|
||
|
|
||
|
# check heap_increase return code
|
||
|
beq $v0, $zero, malloc_hasmem
|
||
|
|
||
|
malloc_error:
|
||
|
# failed to sbrk, return null
|
||
|
la $v0, null
|
||
|
jr $ra
|
||
|
|
||
|
malloc_hasmem:
|
||
|
# set return value, and save ptr size in it
|
||
|
# add 4 to return ptr, since first 4 bytes are INTERNAL
|
||
|
addi $t3, $t7, -4
|
||
|
lw $v0, heap_ptr
|
||
|
sw $t3, ($v0)
|
||
|
addi $v0, $v0, 4
|
||
|
|
||
|
lw $t3, heap_ptr
|
||
|
add $t3, $t3, $t7 # increase ptr by alloc size
|
||
|
sw $t3, heap_ptr
|
||
|
|
||
|
jr $ra
|
||
|
|
||
|
|
||
|
|
||
|
# $a0 : address of ptr
|
||
|
free:
|
||
|
# haha hehe hoho
|
||
|
jr $ra
|
||
|
|
||
|
|
||
|
|
||
|
# $a0 : new size
|
||
|
# $a1 : old ptr
|
||
|
realloc:
|
||
|
# t0 : old ptr size
|
||
|
# t2 : new ptr addr
|
||
|
|
||
|
# check if $a0 is zero, if so then just free
|
||
|
bne $a0, $zero, realloc_inner
|
||
|
move $a0, $a1
|
||
|
la $v0, null
|
||
|
j free
|
||
|
|
||
|
# save to stack
|
||
|
addi $sp, $sp, -12
|
||
|
sw $ra, 0($sp)
|
||
|
sw $a0, 4($sp)
|
||
|
sw $a1, 8($sp)
|
||
|
|
||
|
jal malloc
|
||
|
|
||
|
# pop to stack
|
||
|
lw $ra, 0($sp)
|
||
|
lw $a0, 4($sp)
|
||
|
lw $a1, 8($sp)
|
||
|
addi $sp, $sp, 12
|
||
|
|
||
|
realloc_inner:
|
||
|
addi $a1, $a1, -4
|
||
|
lw $t0, ($a1)
|
||
|
addi $a1, $a1, 4
|
||
|
|
||
|
realloc_loop:
|
||
|
# loop until $t0 or $t1 is zero
|
||
|
beq $t0, $zero, realloc_end
|
||
|
beq $a0, $zero, realloc_end
|
||
|
|
||
|
addi $a1, $a1, 4
|
||
|
addi $t0, $t0, -4
|
||
|
addi $a0, $a0, -4
|
||
|
#lw $t3,
|
||
|
|
||
|
j realloc_loop
|
||
|
|
||
|
realloc_end:
|
||
|
|
||
|
|
||
|
realloc_free:
|
||
|
jr $ra
|
||
|
|
||
|
|
||
|
main:
|
||
|
# push return address
|
||
|
addi $sp, $sp, -4
|
||
|
sw $ra, ($sp)
|
||
|
|
||
|
jal heap_init
|
||
|
|
||
|
li $a0, 24
|
||
|
jal malloc
|
||
|
|
||
|
move $a0, $v0
|
||
|
li $v0, 1
|
||
|
syscall
|
||
|
|
||
|
li $v0, 11
|
||
|
li $a0, 10
|
||
|
syscall
|
||
|
|
||
|
li $a0, 24
|
||
|
jal malloc
|
||
|
|
||
|
move $a0, $v0
|
||
|
li $v0, 1
|
||
|
syscall
|
||
|
|
||
|
li $v0, 11
|
||
|
li $a0, 10
|
||
|
syscall
|
||
|
|
||
|
# pop return address
|
||
|
lw $ra, ($sp)
|
||
|
addi $sp, $sp, 4
|
||
|
|
||
|
exit:
|
||
|
# exit with code 0
|
||
|
li $v0, 0
|
||
|
jr $ra
|