摘要:
本文深入反汇编代码,分析了IAR MSP430普通函数参数传递详情,得出参数传递,前4个寄存器传递,其余的用堆栈传递。
前几天,还很天真以为函数参数传递是从右向左压栈,经过今天的调试看反汇编代码才知道,原来并没有那么简单。事实上,IAR for MSP430环境下,函数参数传递是寄存器和栈混用,即前四个参数用寄存器传递(结构体或联合类型的另外别论),其他的用堆栈传递。
注:本文实验环境是IAR for MSP430 5.51,我在百度文库看到一文档,说是参数传递,前2个是寄存器传递,其余的是堆栈传递,而我实验室得出的是前4个寄存器传递。也许是环境版本差异。另,以下所调试的结果是在关闭优化情况下进行的。
一、普通参数传递
普通参数传递(指不包括结构体或联合类型),前4个参数分别由寄存器R12~R15传递,其他的由堆栈传递。举例如下:
点击(此处)折叠或打开
- void test(int d, char c, char *s, int array[], char buf[], int e, int f)
- {
- d += 1;
- }
- int d = 1;
- char c = 'c';
- char *s = "xyz";
- int array[32];
- char buf[32];
- int e = 5;
- int f = 6;
- test(d, c, s, array, buf, e, f);
1.1 寄存器传递部分
反汇编及相关变量观察窗口如下:
图1 反汇编及相关变量观察窗口
注:细心的话,从观察窗口还可以另一个信息,函数内部局部变量并不是在栈上分配空间,而是寄存器(想想,跟课程所学到的是不是不一样?!)
由此可见,R12~R13分别对应于前4个参数d,c,s,array。值得一提的是,array[32]是在堆栈上分配的空间,而地址0x9B4恰是数组的首地址(传递数组实际上传递指针),如下堆栈所示:
图2 堆栈示意图
1.2 堆栈传递部分
接下来的3个参数,则会被压入栈(因压栈是编译器自动完成,无法单步调试),压栈顺序是从右向左,即f --> e --> buf。执行test函数时,把堆栈的3个参数(buf, e ,f)存放在寄存器。结合SP指针的值及反汇编很容易还原出整个堆栈结构,如下图:
图3 参数入栈示意图
由此,可以推导出R8、R11、R10值,与观察窗口的值一致,如下图:
图4 参数入栈观察窗口参数值
二、我的问题
那如何实现所有参数都是通过堆栈传递呢?这点在处理变参的时候显得很重要,我最近就碰到这个问题。我知道IAR for MCS-51可以在声明函数前加关键字__ext_stack_reentrant达到该目的,但我一直没找IAR for MSP430相对应的关键字。求指点:
附:MSP430寄存器[1]
参考资料:
[1]. MSP430经典讲解.pdf MSP430经典讲解.pdf