曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 11719|回复: 0
打印 上一主题 下一主题

GCC __attribute__ 之 regparm

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-4-15 13:51:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
       在 x86 上,regparm 属性会传递一个数值给编译器,这个数值会告诉编译器要用多少个寄存器来传递函数参数(EAX, EDX 或 ECX,最多 3 个寄存器),通常情况下函数是用堆栈来传递参数的。如果参数比较多,那么其余的参数仍然通过堆栈来传递。

比如我们指定 __attribute__((regparm(0))) ,则表示不用寄存器来传递参数,所有参数都通过堆栈来传递;如果我们指定 __attribute__((regparm(3))),那么就是说会用 3 个寄存器来传递参数(EAX, EDX, ECX),其余的参数通过堆栈来传递。

下面先看不用寄存器来传递参数的情况:
[C++] 纯文本查看 复制代码
#include <stdio.h>

__attribute__((regparm(0))) int parm_to_register (int reg1, int reg2, int reg3, int stack)
{
        return (reg1 + reg2 + reg3 + stack);
}

int main()
{
        int reg1 = 1;
        int reg2 = 2;
        int reg3 = 3;
        int stack = 4;

         parm_to_register(reg1, reg2, reg3, stack);

        return (0);
}

反汇编代码:
.file   "regparm.c"
         .text
.globl parm_to_register
         .type   parm_to_register, @function
parm_to_register:
         pushl   %ebp
         movl    %esp, %ebp
         movl    12(%ebp), %eax
         movl    8(%ebp), %edx
         
         leal    (%edx,%eax), %eax    #leal 指令将 edx 和 eax 中的值相加然后将其和看做是一个地址值送往 eax 中(这样比 movl 更快)
         
         addl    16(%ebp), %eax
         addl    20(%ebp), %eax
         popl    %ebp
         ret
         .size   parm_to_register, .-parm_to_register
.globl main
         .type   main, @function
main:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $32, %esp
         
         #main 中 4 个参数入栈保存
         movl    $1, -16(%ebp)         
         movl    $2, -12(%ebp)
         movl    $3, -8(%ebp)
         movl    $4, -4(%ebp)
         
         #照函数参数从右到左依次入栈保存
         movl    -4(%ebp), %eax
         movl    %eax, 12(%esp)
         movl    -8(%ebp), %eax
         movl    %eax, 8(%esp)
         movl    -12(%ebp), %eax
         movl    %eax, 4(%esp)
         movl    -16(%ebp), %eax
         movl    %eax, (%esp)
         
         call    parm_to_register
         movl    $0, %eax
         leave
         movl    $0, %eax
         addl    $20, %esp
         popl    %ebx
         popl    %ebp
         ret
         .size   main, .-main
         .ident  "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
         .section        .note.GNU-stack,"",@progbits

下面用 regparm 指定函数参数使用 3 个寄存器,即 EAX, EDX, ECX 来保存。将上面 C 程序中的 __attribute__((regparm(0))) 改为 __attribute__((regparm(3))),然后再看一下反汇编:
.file   "regparm.c"
         .text
.globl parm_to_register
         .type   parm_to_register, @function
parm_to_register:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $12, %esp
         
         #分别从 eax, edx, ecx 取出相应的参数值入栈
         movl    %eax, -4(%ebp)
         movl    %edx, -8(%ebp)
         movl    %ecx, -12(%ebp)
         
         #从栈中取出参数进行相加
         movl    -8(%ebp), %eax
         movl    -4(%ebp), %edx
         leal    (%edx,%eax), %eax
         addl    -12(%ebp), %eax
         addl    8(%ebp), %eax
         
         leave
         ret
         .size   parm_to_register, .-parm_to_register
.globl main
         .type   main, @function
main:
         pushl   %ebp
         movl    %esp, %ebp
         pushl   %ebx
         subl    $20, %esp
         
         # main() 中的 4 个参数入栈保存
         movl    $1, -20(%ebp)
         movl    $2, -16(%ebp)
         movl    $3, -12(%ebp)
         movl    $4, -8(%ebp)
         
         #使用 eax, ecx, edx 来传递参数。注意参数存入寄存器的顺序:(reg3-reg1)依次进入 ecx, edx, eax
         movl    -12(%ebp), %ecx
         movl    -16(%ebp), %edx
         movl    -20(%ebp), %eax
         
         #第 4 个参数仍然用栈来传递
         movl    -8(%ebp), %ebx
         movl    %ebx, (%esp)
        
          call    parm_to_register
         movl    $0, %eax
         addl    $20, %esp
         popl    %ebx
         popl    %ebp
         ret
         .size   main, .-main
         .ident  "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
         .section        .note.GNU-stack,"",@progbits
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-28 01:02 , Processed in 0.064336 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表