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 #include2 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, %eax10 11 popl %ebp12 13 ret14 15 f:16 17 pushl %ebp18 19 movl %esp, %ebp20 21 subl $4, %esp22 23 movl 8(%ebp), %eax24 25 movl %eax, (%esp)26 27 call g28 29 leave30 31 ret32 33 main:34 35 pushl %ebp36 37 movl %esp, %ebp38 39 subl $4, %esp40 41 movl $8, (%esp)42 43 call f44 45 addl $1, %eax46 47 leave48 49 ret
动画演示: