2012-04-18 52 views
0

我试图编程一个函数来使用除了4之外的额外参数(因为我的mips版本只支持$ a0- $ a3),但是我的代码不正确。这里是我的代码在主(片段):使用多个mips参数> 4

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,所以即时做一些不正确的事情。任何帮助将不胜感激(和upvoted)

回答

1

在最常见的32位MIPS calling convention,保留空间的堆栈$a0,$a1,$a2$a3,所以调用函数应该期望在16($sp)找到5日的说法。

推测这些东西最简单的方法是用C来写你的函数的一个空的版本,dissassemble的.o文件找出论据是如何被编译通过。

+0

为什么会在堆栈中为寄存器中的参数保留空间?维基百科页面指出,参数5和参数在堆栈上传递,而不是从1到4. – blackcompe 2012-04-18 20:38:36

+1

这就是如何定义调用约定,它确实允许调用例程将其参数保存在堆栈中的已知位置。维基页面不完整。请参阅http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01.pdf。 – markgz 2012-04-18 21:24:23

+0

我明白你的意思,你是正确的。 – blackcompe 2012-04-18 21:48:47

0

该代码是绝对正确的,所以问题在于别处。我最好的猜测是堆栈指针在你的代码中没有被正确地管理,或者在弹出堆栈之前你有一个错误。为什么不使用调试器来查看发生了什么?如果可以的话,发布一个可运行的程序,其中包含所有不相关的代码,以说明问题。 Here是一个可行的MIPS程序,可以完成您正在尝试执行的任务并使用相同的说明。

+0

http://cl.ly/0D1s2j2y400n2I1n2A1h是完整的程序。在printf_branch_args中,我需要计算下一个参数的地址,但我不确定如何做到这一点。 – jfisk 2012-04-18 21:13:27

+0

@jfisk:没有名为'printf_branch_args'的标签。无论如何,这是一个复杂的代码,我不能帮你。我的目标只是回答所提出的问题。 – blackcompe 2012-04-18 22:10:58

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-> format string和3个参数(在$ a1,$ a2和$ a3中)。 请注意,这些评论建议说它会销毁$ s0- $ s6,但从不完整的代码中,我可以说没有通过它就可以恢复多少。总之,你找到的这个printf可能很方便,但它不使用你应该学习的堆栈约定,而且它非常有限。假设您有权使用它,请参阅获取修改权限并将接口重写为理智的内容。请记住,如果您需要一次打印3个以上的变量,则不必多次调用函数(如果是,则只需编写一个包装)。