I understand that whenever I have a function that has more than four arguments in MIPS I should utilize the stack. However in my code below after saving the fifth argument at sw $t0, 4($sp)
and do a jal sad
, then right at the beginning of the sad
function I adjust the stack pointer again to save the $sx
registers that is used by the caller. Am I doing something wrong here?
vbsme: subu $sp, $sp, 8 # create space on the stack pointer
sw $ra, 0($sp) # save return address
li $v0, 0 # reset $v0
li $v1, 0 # reset $v1
li $s0, 1 # i(row) = 1
li $s1, 1 # j(col) = 1
lw $s2, 0($a0) # row size
lw $s3, 4($a0) # col size
mul $s4, $s2, $s3 # row * col
li $s5, 0 # element = 0
loop: bgeq $s5, $s4, exit # if element >= row * col then exit
subi $a3, $s0, 1 # 4th parameter: i-1
subi $t0, $s1, 1
sw $t0, 4($sp) # 5th parameter: j-1
jal sad # calculate the sum of absolute difference using the frame starting from row a3 and col 4($sp)
add $s6, $s0, $s1
andi $s7, $s6, 1
if: bneq $s7, $zero, else
inif: bge $s1, $s2, inelse
addi $s1, $s1, 1
j inif1
inelse: addi $s0, $s0, 2
inif1: subi $s7, $s0, 1
beq $s7, $zero, loop_back
subi $s0, $s0, 1
j loop_back
else: bge $s0, $s2, inelse1
addi $s0, $s0, 1
j inif2
inelse1:addi $s1, $s1, 2
inif2: subi $s7, $s1, 1
beq $s7, $zero, loop_back
subi $s1, $s1, 1
j loop_back
loop_back: addi $s5, $s5, 1
j loop
exit: lw $ra, 0($sp) # restore return address
addi $sp, $sp, 8 # restore stack pointer
jr $ra # return
.globl sad
sad: subu $sp, $sp, 32 # allocate stack space for largest function
sw $s7, 28($sp) # save $s7 value
sw $s6, 24($sp) # save $s6 value
sw $s5, 20($sp) # save $s5 value
sw $s4, 16($sp) # save $s4 value
sw $s3, 12($sp) # save $s3 value
sw $s2, 8($sp) # save $s2 value
sw $s1, 4($sp) # save $s1 value
sw $s0, 0($sp) # save $s0 value
#some code to be filled later
lw $s7, 28($sp) # restore original value of $s7 for caller
lw $s6, 24($sp) # restore original value of $s6 for caller
lw $s5, 20($sp) # restore original value of $s5 for caller
lw $s4, 16($sp) # restore original value of $s4 for caller
lw $s3, 12($sp) # restore original value of $s3 for caller
lw $s2, 8($sp) # restore original value of $s2 for caller
lw $s1, 4($sp) # restore original value of $s1 for caller
lw $s0, 0($sp) # restore original value of $s0 for caller
addiu $sp, $sp, 32 # restore the caller's stack pointer
jr $ra # return to caller's code
This is how its done by gcc. For more information, you (could) should read the Mips ABI. Some things may differ.
http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf
By convention, the fifth argument should go on the fifth word of the stack.
So you should
To store the 5th argument in the stack, you should know this:
If vbsme is going to call another function, then the bottom 4 words of the stack should be saved for the callee to store argument values there. If more than 4 arguments are passed, then an additional word should be saved for each argument.
Also, the $ra register should be saved at the top of the stack, since its register 31.
In response to
Yes, $sp + 24 points to the base of the caller´s stack. However, thats not where I placed the fifth argument. The fifth argument is placed on the fifth word of the callers stack, thats why I add 16.