《Linux内核分析》第一周学习笔记 计算机是如何工作的
郭垚 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
1. 存储程序计算机工作模型
1.1 冯诺依曼体系结构
冯诺依曼体系结构,即具有存储程序的计算机的体系结构。超级计算机都可以用这种体系描述。
1.2 存储程序计算机工作模型
- 从硬件上看:CPU与内存之间由总线连接,CPU中一个关键寄存器IP(在16位CPU中叫IP,在32位CPU中叫EIP,在64位CPU中叫RIP)总是指向内存中某块区域,IP指向内存中的代码段CS。CPU执行IP指向的指令,执行完后IP自加1继续执行下一条指令。
- 从软件上看:内存保留指令和数据,CPU解释、执行这些指令。
1.3.1 API与ABI
- API:程序员与计算机的接口界面。
- ABI:程序与CPU接口界面,多数指令可直接访问内存。
1.3.2 EIP
在32位X86计算机中指向内存的某条指令,EIP可自加到下一条指令(指令长度不同),也可被其他指令(CALL、RET、JMP、condition JMP)修改。
2. X86汇编基础
2.1 X86 CPU的寄存器
2.1.1 通用寄存器
32位的寄存器中,低16位作为16位的寄存器:AX、BX、CX、DX。一般开头增加了E的寄存器是32位。如:累加器EAX、基地址寄存器EBX、计数寄存器ECX、数据寄存器EDX、堆栈基指针EBP、变址寄存器ESI和EDI、堆栈顶指针ESP
2.1.2 段寄存器
- 指令都存储于代码段,CPU实际取指令的时候通过cs:eip来描述。
- 每个指令都有一个堆栈
2.1.3 标志寄存器
标志寄存器用于标识当前状态。
2.2 常见汇编指令
2.2.1 mov指令及几种内存寻址方式
后缀b,w,l,q分别代表8,16,32,64位
- 寄存器寻址movl %eax,%edx(操作的都是寄存器,与内存无关)
- 立即寻址movl $0x123,%edx($表示立即数,立即寻址与内存无关)
- 直接寻址movl 0x123,%edx(没有$则表示地址,将内存地址0x123指向的内存数据放入edx寄存器)
- 间接寻址movl (%ebx),%edx(将寄存器ebx存的值作为内存地址,将内存地址存储的数据放入edx)
- 变址寻址movl 4(%ebx),%edx(在间接寻址前改变寄存器的值,本句是+4)
注:Linux使用的A&T汇编格式与Intel汇编略有不同。
2.2.2 几个重要的汇编指令
- movl %eax,(%esp) 将eax放到esp所在的内存位置。()可表示该寄存器指向的值
- call 0x1234 调用0x1234这个地址(eip存储着cpu要读取指令的地址,此句表示CPU下条指令从0x1234开始执行)
- ret是把之前保存的eip弹出,ret后会继续执行函数调用完的下一条指令
- *表示是伪指令,不能被程序员直接使用。因为eip寄存器不能被直接修改,只能间接修改。
2.3 堆栈练习
例1:
例2:
例3:
堆栈过程分析:
3. 汇编一个简单的C程序
3.1 将C代码编译成汇编代码
gcc -S -o main.s main.c -m32
实验环境为64位,-m32将代码编译为32位的汇编代码main.s
3.2 enter与leave指令
- enter将在栈上新建一个空栈
- leave撤销函数调用堆栈
注:
- 函数调用堆栈是由逻辑上多个堆栈叠加起来的。
- 函数的返回值默认用%eax存储返回给上一级函数。
- pop %ebp 意思是ebp指回上一次的位置
3.3 实验
实验过程截图:
C程序源代码:
汇编代码:
堆栈过程分析:
4.总结
根据本门课程中老师对冯诺依曼原理体系的讲解,我了解到计算机的基本原理是存储程序和程序控制。计算机由CPU、I/O总线、输入输出系统、存储器以及I/O设备组成。其中CPU与内存之间由总线连接,内存保留指令和数据,CPU解释、执行这些指令。每一条指令中明确规定了计算机从哪个地址取数,进行什么操作,然后送到什么地址去等步骤。CPU中一个关键寄存器IP总是指向内存中某块区域。计算机在工作时会先从内存中取出一条IP指向的指令给CPU执行,按指令的要求从存储器中取出数据进行指定的运算和逻辑操作,然后再把结果送到内存中去。执行完后IP自加1继续执行下一条指令,则再取出第二条指令依此进行下去。直至遇到停止指令。由此可以看出,计算机能完成很多复杂的计算实质上都是依赖于简单的一步一步地取出指令,自动地完成指令规定的操作。