最近在看《深入理解计算机系统这本书》,对于它汇编出来的代码不能理解呢。
源文件中含以下代码
1 int simple(int *xp, int y)
2 {
3 int t = *xp + y;
4 *xp = t;
5 return t;
6 }
使用-S -01运行GCC 产生的汇编代码有以下一段:
1 simple:
2 pushl %ebp
3 movl %esp,%ebp //这个时候栈顶存的是什么要给栈基址的?
4 movl 8(%ebp),%eax //这个里面的8和12是怎么得出来的呀,bdp+4 又是什么东西呢?
5 movl (%eax),%edx
6 addl 12(%ebp),%edx
7 movl %edx,(%eax)
8 movl %edx,%eax //书上说这里完成了把t作为返回值,这一点是怎么做到的?
9 movl %ebp,%esp
10 popl %ebp
11 ret
我自己理解不通呢,知道自己有很多理解错误以及不够的地方,希望大神们来教下小虾米哈,注释后面是我不能理解的地方。
------解决方案--------------------
通常情况下在 x32程序 函数用 Eax 作为返回值
去了解下 stdcall 调用约定
;这里将esp 赋给ebp 是为了方便计算偏移
pushl %ebp
movl %esp,%ebp
;此时堆栈情况
int y ;ebp + 12
int *xp ;ebp + 8
函数返回地址 ;ebp + 4
ebp ;ebp + 0
参数 int *xp 与参数 int y 占用空间均为4字节
------解决方案--------------------
栈,也是在普通的存储空间里,当以栈的方式来访问时,才遵循先进后出,以其它方式来访问,就随意了;这样以不同的方式来操作同一数据存储结构,类似于高级语言里对变量访问的类型转换(好像是越来越不被支持了?)。
------解决方案--------------------
1 simple: ;[0-retaddr,4-par2,8-par1]
2 pushl %ebp ;[0-(old_ebp),4-retaddr,8-par2,12-par1]
3 movl %esp,%ebp //这个时候栈顶存的是什么要给栈基址的? ; ^new_ebp==esp
4 movl 8(%ebp),%eax //这个里面的8和12是怎么得出来的呀,ebp+4 又是什么东西呢?retaddr
5 movl (%eax),%edx
6 addl 12(%ebp),%edx ; edx=par2+par1
7 movl %edx,(%eax) ; eax=edx
8 movl %edx,%eax //书上说这里完成了把t作为返回值,这一点是怎么做到的? ; 规定/约定eax中保存返回值
9 movl %ebp,%esp
10 popl %ebp ;[0-retaddr,4-par2,8-par1]
11 ret ; ^esp
... ;[]
push par1 ;[0-par1]
push par2 ;[0-par2,4-par1