第四周汇编2课堂测试画的图抽象且不完整,这里做一下补充。
(1)源代码:
int g(int x){
return x+3;
}
int f(int x){
int i=2;
return g(x)+i;
}
int main(void){
return f(8)+1;
}
(2)汇编代码:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $3, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $2, -4(%ebp)
pushl 8(%ebp)
call g
addl $4, %esp
movl %eax, %edx
movl -4(%ebp), %eax
addl %edx, %eax
leave
ret
main:
pushl %ebp
movl %esp, %ebp
pushl $8
call f
addl $4, %esp
addl $1, %eax
leave
ret
(3)调试
disassemble
可以看到main函数的汇编代码,用i r
(info registers)查看各寄存器的值。display /i $pc
可以使每次执行下一条汇编语句时都会显示出当前执行的语句。
单步执行pushl $8
,esp减4从0xbffff118变为0xbffff114。用 x $esp
查看esp所指位置所存放的值,可以看到是push进去的8。
单步执行call f
,esp减4从0xbffff114变为0xbffff110,ebp不变依然是0xbffff118。用 x $esp
查看esp所指位置所存放的值,0x08048411应该是call f
的下一句地址。
单步执行了pushl %ebp
,esp减4从0xbffff110变为0xbffff10c。用 x $esp
查看esp所指位置所存放的值,0xbffff118是push进去的ebp的值。
执行 movl %esp, %ebp
和subl$16, %esp
后,ebp为0xbffff10c,esp为0xbffff0fc。下一句movl $2, -4(%ebp)
是将立即数放到ebp减4的位置,可以通过x/8x $esp
查看esp向上8个字节的所有位置所放的值(当然也可以查看ebp):
可以看到0xbffff108中放的值为“2”。继续执行pushl 8(%ebp)
,下一句 call g
,将call g
的下一句地址0x080483fb压栈。
继续执行到g函数的pop %ebp
,可以看到中eax的值变为11,ebp恢复到0xbffff10c。
ret
将弹出当初压栈的call g
下一句addl $4, %esp
的地址eip指向0x080483fb。
(4)堆栈变化