[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) 而多出的参数将通过堆栈传递. 堆栈传递总是最后一个先入栈.