汇编指令与C语言对比
这两天在巩固基础,重拾汇编语言,对于汇编语言的思考,记录在此,仅仅是自己的思考笔记,可能有错误的地方,欢迎提意见。
计算机两个最主要的组成部分,就是CPU和内存了。我们编写的程序要运行,是需要先加载到内存中,然后由CPU控制执行的。
简而言之,我们写的程序,其实就是使用CPU对内存进行操作,即CPU和内存的交互,CPU是通过内部的寄存器和内存交互的,所以程序就是寄存器和内存的交互。
重要的事情说三次,寄存器和内存的交互,寄存器和内存的交互,寄存器和内存的交互。 请牢记这句话,我们通篇文章都会贯穿这种思想。
一般c语言的教程,都包含这几个部分:
- 变量和数组(内存)
- 控制(if, for)
- 函数(栈)
我们就来看看,以上这些知识,是怎么跟汇编语言联系起来的(这里讲的是8086汇编)。
寻址
8086 CPU是16位处理器,即其内部的寄存器是16位的,但是呢8086的地址总线却是20位的。那这么说,寄存器是否只能访问到2的16次方个内存地址,其他的内存无法访问了吗?
为了解决这个问题,聪明的硬件设计师们将寄存器分为两类,段寄存器和通用寄存器。寻址时,通过段寄存器左移4位+通用寄存器来确定一个内存地址,这样就能访问到所有的内存单元了。
8086 CPU中的寄存器个数很少,每个都有名字(代号)。8086 CPU总共有14个寄存器。
- 段寄存器:CS(Code Segment),DS(Data Segment),SS(Stack Segment),ES(Extend Segment)
- 通用寄存器:AX,BX(Base),CX(Count),DX
这里需要注意的是,所有的内存包括显存和ROM是统一编址的。
指令和数据的区分
计算机的世界里只有0101,那么CPU是怎么区分这个0101代表的是指令还是数据呢?通过寄存器,如上。
CS左移4位+IP寄存器所得的地址,其指向的地址存储的0101,就是下一条即将指向的指令。
DS就是代表的数据,SS代表栈。
寄存器的常用组合
寄存器一般的搭配为:
- CS+IP:指定指令地址
- DS+([0], [BX], [BX+0], [SI], [DI]) :指定数据地址,BX寄存器存放偏移地址,SI和DI可以用于复制
- SS+SP:指定栈内存
- loop+CX:CX寄存器放置循环次数
- DS+[BX+SI+0]:可以用于数组,该命令格式也可以写为,200[SI]或[BX][SI]或[BX][SI]这种更像数组的写法
内存
在C语言中,我们不需要直接指定内存的地址来获取数据,但在汇编中,是需要我们指定地址的。每一个内存单元代表一个字节(8位),所以一个寄存器为16位则需要两个字节存放。高地址存放在高位,低地址存放低位。如下图,
## 汇编指令和C语言对比
### 变量和数组(内存)
- 变量和数组:变量和数组的分配都是在内存中。如
int i = 0;
或者int[] array = {1, 2}
,在汇编中则是mov [0], 0
或者mov [BX],1; add BX,2; mov[BX],2;
控制(if, for)
- go跳转语句:在汇编中则是jmp short, jmp far ptr,该命令操作了CS和IP寄存器。jmp far ptr段间跳转,不止修改了IP的值还修改了CS的值,而jmp short只修改IP的值
- if判断:在汇编中是JE指令,相等则跳转。
- for, while循环:for在汇编中是loop+CX,其中CX设置循环次数,while则可以使用JE跳转
函数(栈)
- 函数的调用和返回指令:call, call far ptr, ret, retf,该指令会把IP或CS和IP入栈,
中断
中段可以认为就是不断检测系统发生的事件,然后系统先停下手头的工作响应中断,根据中断类型找到中断程序的入口,执行该中断处理程序,完成后返回。