gpt4 book ai didi

具有四个以上参数的 MIPS 函数调用

转载 作者:行者123 更新时间:2023-12-01 04:41:55 24 4
gpt4 key购买 nike

我知道每当我在 MIPS 中有一个超过四个参数的函数时,我都应该使用堆栈。但是,在我将第五个参数保存在 sw $t0, 4($sp) 之后,下面的代码中并做一个 jal sad ,然后就在 sad 的开头函数我再次调整堆栈指针以保存 $sx调用者使用的寄存器。我在这里做错了吗?

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

最佳答案

gcc 就是这样完成的。有关更多信息,您(可以)应该阅读
Mips ABI。有些事情可能会有所不同。

http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf

按照惯例,第五个参数应该放在堆栈的第五个字上。

所以你应该

sad:
sub $sp,$sp,24 #24 byte stack frame
... some code ...
#Convention indicates to store $a0..$a3 in A..D (see below)
sw $a0,0(sp)
sw $a1,4(sp)
sw $a2,8(sp)
sw $a3,12(sp)

#Get the 5th argument
lw $t0,40($sp) #40 : 24 + 16

要将第 5 个参数存储在堆栈中,您应该知道:

如果 vbsme 将调用另一个函数,那么堆栈的底部 4 个字应该被保存以供被调用者在那里存储参数值。如果传递的参数超过 4 个,则应为每个参数保存一个额外的单词。
vbsme's stack frame bottom part (Argument building area)

| ... |
---------------
| 5th arg | <---- sw $t5,16($sp)
---------------
| D |
---------------
| C |
---------------
| B |
---------------
| A |
--------------- <--sp (of vbsme stack frame)

另外,$ra 寄存器应该保存在栈顶,因为它的寄存器是 31。
vbsme:  
subu $sp, $sp, 20+N # 20: space for 5 arguments,
#N space for other stuff (ra,$tx, etc)


#Set arguments (assumes 5th parameter value is in register $t5)
subi $a3, $s0, 1 # 4th parameter: i-1
sw $t5,16($sp) #

...
.end

回应
Why is it that you do: 
lw $t0,40($sp)
to get the 5th argument, why did you add 24 to 16? when you do
sub $sp,$sp,24
don't you already move
the sp 24 place?

是的,$sp + 24 指向调用者堆栈的底部。然而,这不是我提出第五个论点的地方。第五个参数放在调用者堆栈的第五个字上,这就是我添加 16 的原因。

关于具有四个以上参数的 MIPS 函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2298838/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com