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 |
|
popl %eax |
movl(%esp),%eax |
|
call 0x12345(调用0x12345地址) |
pushl %eip(*)(当前的eip压栈) |
|
ret |
popl %eip(*) |
|
enter |
pushl %ebp |
|
leave |
movl %ebp,%esp |
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
动画演示: