Aiur – ZelluX 的技术博客

Security, Kernel, Virtualization, Programming Languages

[zz]asmlinkage & regparm

107 views | without comments

发信人: feiy (积极、乐观、率性、自信), 信区: KernelTech
标  题: asmlinkage 其他 regparm attribute函数的gcc汇编浅析
发信站: BBS 水木清华站 (Mon Apr 26 02:56:12 2004), 转信

[asmlinkage 其他 regparm attribute函数的gcc汇编浅析]

asmlinkage是一类特殊的regparm attribute函数:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

下面的分析基于:c 源码 tt.c, 汇编代码 tt.S, shell命令是
gcc -S tt.c -o tt.S  gcc version 3.2.2, cpu 386+

1. C 源码

__attribute__((regparm(0~3))) int cal(int a, int b, int c, int d)
{
return a + b + c + d;
}
int main()
{
int  r1=1;
int  r2=2;
int  r3=3;
int  r4=4;

cal(r1, r2, r3, r4);

return 0;
}

2. 当__attribute__((regparm(0))) int cal(int a, int b, int c, int d)
gcc编译得到下述汇编代码

.file    "tt.c"
.text
.globl cal
.type    cal,@function
cal:
pushl   %ebp
movl    %esp,     %ebp
movl    12(%ebp), %eax  # 从 堆栈 中取出传递给函数的第二个参数 b
addl    8(%ebp),  %eax  # 从 堆栈 中取出传递给函数的第一个参数 a
addl    16(%ebp), %eax  # 从 堆栈 中取出传递给函数的第三个参数 c
addl    20(%ebp), %eax  # 从 堆栈 中取出传递给函数的第四个参数 d
leave
ret
.Lfe1:
.size    cal,.Lfe1-cal
.globl main
.type    main,@function
main:
pushl    %ebp
movl    %esp, %ebp
subl    $24, %esp
andl    $-16, %esp
movl    $0, %eax
subl    %eax, %esp
movl    $1, -4(%ebp)
movl    $2, -8(%ebp)
movl    $3, -12(%ebp)
movl    $4, -16(%ebp)
pushl   -16(%ebp)       # 参数通过堆栈传递, 把要传递给函数的第四个参数压栈
pushl   -12(%ebp)       # 第三个参数入栈  注:这里的ebp用来指示main函数的局
pushl   -8(%ebp)        # 第二个参数入栈     部变量,-4(%ebp)存放的是第一
pushl   -4(%ebp)        # 第一个参数入栈     个局部变量r1,-4属于分配上的
call    cal             #                  巧合, 这里的-4与r1将作为传递给函
#                  数的第一个参数没有必然的关系。
addl    $16, %esp
movl    $0, %eax
leave
ret
.Lfe2:
.size    main,.Lfe2-main
.ident    "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"

3. 当__attribute__((regparm(3))) int cal(int a, int b, int c, int d)
得到下述汇编代码

.file    "tt.c"
.text
.globl cal
.type    cal,@function
cal:
pushl    %ebp
movl    %esp, %ebp
subl    $12, %esp
movl    %eax, -4(%ebp)  # 从 %eax 中取出传递给函数的第一个参数 a
movl    %edx, -8(%ebp)  # 从 %edx 中取出传递给函数的第二个参数 b
movl    %ecx, -12(%ebp) # 从 %ecx 中取出传递给函数的第三个参数 c
movl    -8(%ebp), %eax
addl    -4(%ebp), %eax
addl    -12(%ebp), %eax
addl    8(%ebp), %eax   # 从 堆栈 中取出传递给函数的第四个参数 d
leave
ret
.Lfe1:
.size    cal,.Lfe1-cal
.globl main
.type    main,@function
main:
pushl    %ebp
movl    %esp, %ebp
subl    $24, %esp
andl    $-16, %esp
movl    $0, %eax
subl    %eax, %esp
movl    $1, -4(%ebp)
movl    $2, -8(%ebp)
movl    $3, -12(%ebp)
movl    $4, -16(%ebp)
subl    $12, %esp
movl    -12(%ebp), %ecx   # 通过 ecx  向函数传递第三个参数 r3
movl    -8(%ebp), %edx    # 通过 edx  向函数传递第二个参数 r2
movl    -4(%ebp), %eax    # 通过 eax  向函数传递第一个参数 r1
pushl    -16(%ebp)        # 通过 堆栈 向函数传递第四个参数 r4
call    cal
addl    $16, %esp
movl    $0, %eax
leave
ret
.Lfe2:
.size    main,.Lfe2-main
.ident    "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"

4. 结论

1) __attribute__((regparm(0~3))) 用来指定函数调用时通过寄存器传递参
数的个数

2) if any, 从第一个参数起, 依此通过 eax, edx, ecx 传递参数,

3) 而多出的参数将通过堆栈传递. 堆栈传递总是最后一个先入栈.

Related Posts

Written by zellux

August 20th, 2008 at 9:53 pm

Posted in Programming

Tagged with ,

Leave a Reply

FireStats icon Powered by FireStatsBetter Tag Cloud