1.冯诺依曼体系结构(存储程序计算机)
1.1 解释
CPU与内存通过总线连接,CPU中有很多寄存器(总是指向内存的某一块区域),如IP(Instruction Pointer)。假如指向CS(Code Segment,代码段),CPU从IP指向的内存的地址,取指令执行,执行过后IP自加1,取下一条指令,重复上述步骤。
CPU不断执行next instruction,从内存取指令不断执行。
内存保存数据和指令,CPU负责解释和执行指令。
1.2 API和ABI
cpu识别什么指令,怎么定义?
API:程序员与计算机的接口界面
ABI:程序与CPU的接口界面
2.×86寄存器
2.1 通用寄存器
2.2 段寄存器
CPU在实际取指令是根据cs:eip来确定一个指令
3.×86汇编指令
指令 |
含义 |
模式/模型 |
movl %eax,%edx |
edx=eax |
register mode,以%开头的寄存器标示符 |
movl $0x123,%edx |
edx=0x12 |
immediate,立即数以$开头的数值 |
movl 0x123(没有$符表示地址),%edx |
edx=*(int32_t*)0x123 |
direct,直接访问一个指定的内存地址的数据 |
movl (%ebx)(ebx寄存器存的值——内存地址,加括号表示内存地址存的数据放在ebx),%edx |
edx=*(int32_t*)ebx |
indirect,将寄存器的值作为一个内存地址来范围内存 |
movl 4(%ebx),%edx |
edx=*(int32_t*)(ebx+4) |
displaced,在间接寻址时改变寄存器的值 |
pushl %eax |
subl $4,%esp movl %eax,(%esp) |
|
popl %eax |
movl(%esp),%eax addl $4,%esp |
|
call 0x12345(调用0x12345地址) |
pushl %eip(*)(当前的eip压栈) movl $0x12345,%eip(*)(立即数放在eip) |
|
ret |
popl %eip(*) |
|
enter |
pushl %ebp movl %esp,%ebp |
|
leave |
movl %ebp,%esp popl %ebp |
|
b,w,l,q分别代表8位,16位,32位,64位
eip指向内存的指令,自加一(一条指令),*代表这些指令不能被程序员直接使用,程序不能直接修改eip寄存器
4.汇编代码分析
1 #include <stdio.h>
2
3 int g(int x)
4
5 {
6
7 return x + 3;
8
9 }
10
11
12
13 int f(int x)
14
15 {
16
17 return g(x);
18
19 }
20
21
22
23 int main(void)
24
25 {
26
27 return f(8) + 1;
28
29 }
gcc -S -o main.s main.c -m32,对应的汇编代码
1 g:
2
3 pushl %ebp
4
5 movl %esp, %ebp
6
7 movl 8(%ebp), %eax
8
9 addl $3, %eax
10
11 popl %ebp
12
13 ret
14
15 f:
16
17 pushl %ebp
18
19 movl %esp, %ebp
20
21 subl $4, %esp
22
23 movl 8(%ebp), %eax
24
25 movl %eax, (%esp)
26
27 call g
28
29 leave
30
31 ret
32
33 main:
34
35 pushl %ebp
36
37 movl %esp, %ebp
38
39 subl $4, %esp
40
41 movl $8, (%esp)
42
43 call f
44
45 addl $1, %eax
46
47 leave
48
49 ret
动画演示: