2

我试图通过将它们推入堆栈来编写一个函数以使用除 4 之外的额外参数(因为我的 mips 版本仅支持 $a0-$a3),但我的代码不正确。这是我在主要(片段)中的代码:

li $t0,40 #temp value for our 5th arg.

addi $sp, $sp, -4 #decrement stack pointer by 4
sw $t0, 0($sp) #save the value of $t0 on the stack.

jal printf

它将临时值设置为 40,在堆栈上提供空间并保存它。然后调用我的函数。作为测试是否有效,当我将这些临时参数 $a0-$a3 移动到它们保存的寄存器对应项时,在函数内部,我有以下代码:

lw $t0, 0($sp) 
addi $sp, $sp, 4
move $a0,$t0

li $v0, 1
syscall

...但它只打印出 0 而不是 40,所以我做错了什么。任何帮助将不胜感激(并赞成)

4

3 回答 3

3

在最常见的 32 位 MIPS调用约定中,堆栈上为$a0,$a1,$a2and保留空间$a3,因此被调用函数应该期望在 处找到第 5 个参数16($sp)

解决这些问题的最简单方法是用 C 编写函数的空版本,然后反汇编.o文件以找出编译器如何传递参数。

于 2012-04-18T18:11:07.397 回答
0

通过查看上面链接的完整代码,您正在处理两个问题。

1)您的堆栈没有正确设置以使用标准 MIPS o32 调用约定的参数(尤其是四个以上)。其他答案很好地指出了您对此的帮助。

2)您使用的“printf”不使用标准调用约定。如果你看到评论:

## printf--
## A simple printf-like function. Understands just the basic forms
## of the %s, %d, %c, and %% formats, and can only have 3 embedded
## formats (so that all of the parameters are passed in registers).
## If there are more than 3 embedded formats, all but the first 3 are
## completely ignored (not even printed).
## Register Usage:
## $a0,$s0 - pointer to format string
## $a1,$s1 - format argument 1 (optional)
## $a2,$s2 - format argument 2 (optional)
## $a3,$s3 - format argument 3 (optional)
## $s4 - count of formats processed.
## $s5 - char at $s4.
## $s6 - pointer to printf buffer

预计不会在堆栈上传递任何内容。(记住 $s0-6 与堆栈无关)。您可以向此函数提供 $a0-> 格式字符串和 3 个参数(在 $a1、$a2 和 $a3 中)。请注意,这些评论表明它会破坏 $s0-$s6,尽管从不完整的代码中,我可以说恢复了多少,而无需跟踪它。简而言之,您找到的这个 printf 可能很方便,但它不使用您应该学习的堆栈约定,而且非常有限。假设您有权使用它,请参阅获得修改权限并将界面重写为理智的东西。请记住,如果您需要一次打印超过 3 个变量,则必须多次调用该函数并不是什么大问题(如果是,只需编写一个包装器)。

于 2012-04-23T21:32:45.130 回答
0

该代码绝对正确,因此问题出在其他地方。我最好的猜测是堆栈指针在你的代码中没有得到正确的管理,或者printf你在弹出堆栈之前有一个错误。为什么不使用调试器来查看发生了什么?如果可以,请发布一个可运行的程序,删除所有不相关的代码来证明问题。是一个有效的 MIPS 程序,它可以执行您尝试执行的操作并使用相同的指令。

于 2012-04-18T20:36:24.850 回答