下面是一段AT&T汇编语言代码:
g:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
addl $3,%eax
popl %ebp
ret
f:
pushl %ebp
movl %esp,%ebp
subl $4,%esp
movl 8(%ebp),%eax
movl %eax,(%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp,%ebp
subl $4,%esp
movl $8,(%esp)
call f
addl $1,%eax
leave
ret
与分析C
语言一样,我们从main段开始分析:
main:
pushl %ebp ;将ebp的值压入栈中(ebp的值为0)
movl %esp,%ebp ;将扩展栈寄存器的值放进基址指针寄存器中
subl $4,%esp ;把esp向下移动一个单位
movl $8,(%esp) ;将立即数8放入esp当前指向的位置
call f ;执行f处的指令
addl $1,%eax
leave
ret
此时CPU
就会在f处读指令了:
f:
pushl %ebp ;将ebp中的数据压入栈中
movl %esp,%ebp ;将扩展栈寄存器的值放进基址指针寄存器中
subl $4,%esp ;把esp向下移动一个单位
movl 8(%ebp),%eax ;eax = 8 (ebp变址寻址8)
movl %eax,(%esp) ; esp = 8
call g ;调用g段的代码
leave
ret
执行g处的指令:
g:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax ;eax = 8
addl $3,%eax ;eax = 11
popl %ebp
ret
这段代码其实对应着一段C代码:
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 1;
}