X86和ARM函数调用中参数传递和返回值 @ 12/25/2004

学习类
from: http://treezhao.blogchina.com/blog/refer.310145.html

arm属于RISC指令集,而x86则是CISC指令集的代表,编译器生成的结果比较有代表性。其中,参数传递和返回值是汇编/C混合编程比较关注的部分,尤其是在bootloader中编程中非常重要。总的来说,RISC倾向于寄存器穿参数,而x86则是通过堆栈传参数。而返回值则都通过效率最高的寄存器完成,arm中是r0,x86是eax。

以下的示例是通过写一个简单例子,并且反编译objdump来看生成的汇编来了解这些机制,呵呵,比较实验化,可是也只能这样了,编译技术也不是那么简单就能理解得了的。注意,这样,编译选项影响就可能比较大,我的实验仅局限在加/减-O选项,而其他的比较细节的就无能为力了。不过,这个方法对我理解参数和返回值这点来说,还是比较有效的。

1  返回值:
1) X86采用eax作为返回值。
return i;          2d: 89 c0                        mov    %eax,%eax

2) ARM使用r0作为返回值。
RETURN I;      4C: E1A00003            MOV R0, R3

2 参数传递
1) X86:主要是采用堆栈,除非指定以寄存器传递(通过"regparm (NUMBER)"注:NUMBER<=3指定)。
如果指定寄存器传递参数,则eax为第一个参数,edx为第二个参数, ecx为第三个参数。
int hello(int );
t=hello(13);              9: 6a 0d            push  $0xd
                              b: e8 fc ff ff ff      call  <hello>
2) ARM:寄存器到堆栈,首先将参数赋给r0, r1等,同时,未经优化的代码,在函数的堆栈中,也会为每个参数预留一个参数堆栈。
ARM的参数结构看起来比较奇怪,对其的解释是:出于效率考虑,如果在函数中的寄存器足够分配的话,则经过优化后,它不会进栈,而直接使用寄存器即可。这样的方式可以保证优化只局限于函数内部,实际上一般使用-O优化过的代码最终普遍在函数中不再进栈的。
int hello(int );
t=hello(13);

未优化: 10: e3a0000d  mov r0, #13 ; 0xd 
            14: ebfffffe      bl <hello>
            ... ...
            <hello>
            ......
            3c: e50b0010  str r0, [fp, -#16]
优化后:-O选项
            4: e3a0000d  mov r0, #13 ;
            ...
            bl <hello>
            ...
          1c: e1a0f00e  mov pc, lr
发布于 12/25/2004 3:17:38 | 评论:0

看帖要回帖...

categories
archives
links
statistics
  • 网志数:1168
  • 评论数:2011