1.冯诺依曼体系结构——存储程序式计算机
冯诺依曼体系结构核心是存储程序,将数据和代码都存储在存取器中,都是二进制数据,通过特定模块来区分数据和代码。冯诺依曼体系结构的计算机包括运算器、控制器、存储器、输入单元、输出单元五大件。
image
2.x86汇编
2.1 32位CPU寄存器结构
x86寄存器结构.png1.开头为e的寄存器一般都为32位寄存器,以R开头的寄存器一般为64位寄存器
2.通常情况下eax作为累加器,ebx作为基址寄存器,ecx作为计数器,edx作为数据寄存器,ebp作为堆栈基指针寄存器(栈底),esi、edi作为变址寄存器,esp作为堆栈顶指针寄存器。
2.2 汇编指令
1.mov:movl l 代表32位
register mode :寄存器寻址。
immediate:立即寻址 $+数字:代表的是一个立即数。只有数字:代表的是一个地址
direct:直接寻址。直接访问一个指定的内存地址数据
indirect:间接寻址。将ebx中存储的值作为一个地址,从这个地址取出的值赋给edx
displaced:变址寻址。
2.pushl:入栈
栈是向下增长的,ebp(栈基址指针)指向栈底,esp(堆栈顶指针)指向栈顶。入栈:esp向乡下移动4个字节,然后将eax中的值村放入esp中。
pushl %eax相当于:
subl $4, %esp
movl %eax, (%esp)
3.popl: 出栈
popl %eax相当于:
movl (%esp), %eax
add $4, %esp
4.call 0x12345:
pushl %eip(*)
movl 0x12345, %eip(*)
eip寄存器,用来存储CPU下一条要执行的指令的地址
5.ret
popl %eip(*)
(*)表示 程序员不能直接使用
6.leave:
movl %ebp, %esp
pop %ebp
3.C程序反汇编分析
代码如下:
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 1;
}
编译成汇编代码:
gcc -S main.c -o main.s -m32 //以32位编译
汇编后的代码(去掉以.开头的部分,这部分是编译器链接用的)
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
eip:当一个指令执行完成之后,自动指向下一个指令
eax:函数返回值默认使用eax寄存器存储返回给上一级函数
接下来,分析一下堆栈调用过程:
首先main():假设栈在内存中的起始地址为0,ebp和esp均指向栈首地址0.
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $8, (%esp)
以上代码为:main函数中开辟新的内存区域,然后将参数 8 入栈、
image
接下来,调用
call f
call f 相当于;
pushl %eip
movl f, %eip
eip中存的是当前指令的的地址。首先将eip入栈,然后将f中第一个指令的地址赋给eip。此时栈情况如下图所示:
image
此时,此时eip指向f中的pushl %ebp
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
为f函数开辟栈空间,然后将参数8赋值给eax,最后将eax入栈,具体操作过程如下:
image
接下来,运行
call g
调用g函数,此时栈情况如下:
image
接下来,执行
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $3, %eax
popl %ebp //将ebp指向的值赋给ebp
ret//相当于:popl eip
栈调用过程如下:
image
此时,eip指向否f函数中的 leave
leave
ret
此时eip指向 MIan函数中的 addl $1, %eax
image
接下来执行 main函数
addl $1, %eax//11 + 1
此时eax = 12
接下来执行
leave
ret
image
4.总结
堆栈:高级语言的函数调用。是高级语言的基础
堆栈是C程序运行时必须的一个记录调用路径和参数的空间。
堆栈作用:
- 函数调用框架
- 传递参数
- 保存返回地址
- 提供局部变量空间
网友评论