mips/test/masm/test.asm

243 lines
3.3 KiB
NASM
Raw Normal View History

# 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