前言
首先在这里道个歉,看到有很多的朋友对这个专栏挺感兴趣的,这章其实很早就写好了,但由于那时候列表无法实现三列,我也和开发人员沟通了,之后因为一些自身的原因,耽误了一些时间,再次说声抱歉 很多人可能觉得汇编语言是低级语言,很复杂且没有太大实用性,这里我不太认同,我见过那些 把nasm玩的非常溜的 在计算机内核之间遨游,这也是我学习逆向所追求的
几条汇编指令
汇编指令 | 控制CPU完成的操作 | 用高级语法描述 |
---|---|---|
Mov ax,18 | 将18送入寄存器AX | AX=18 |
Mov ah,78 | 将78送入寄存器AH | AH=78 |
dd ax,8 | 将寄存器AX中的数值加上8 | AX=AX+8 |
Mov ax,bx | 将寄存器BX中的数据送入寄存器AX | AX=BX |
Add ax,bx | 将AX和BX中的数值相加,结果存在AX中 | AX=AX+BX |
注意:在写一个寄存器和汇编指令的时候 不区分大小写,mov ax,18 和MOV AX,18意义相同;BX和bx的含义一样
原AX中的值:0000H,原BX中的值:0000H
程序段中的指令 | 指令执行后的AX中的数值 | 指令执行后BX中的数值 |
---|---|---|
Mov ax,4E20H | 4E20H | 0000H |
Add ax,1406H | 6226H | 0000H |
Mov bx,2000H | 6226H | 2000H |
Add ax,bx | 8226H | 2000H |
Mov bx,ax | 8226H | 8226H |
Add ax,bx | Ax加BX的结果 | 8226H |
思考一下,最后一条指令执行后 AX中的结果是什么?
分析:
程序段最后一条指令是add ax,bx, 在执行之前ax和bx的数据都为8226H,意思前面介绍过为AX加BX的结果存放在寄存器AX中
所以所得的值是:1044CH,但是由于AX是16位寄存器,只能存放4位16进制数,所以最高位的1不能在AX中保存,AX的数据最终为 044CH。
|程序段中的指令|指令执行后AX中的数值|指令执行后BX中的数值|
|-|-|-|
|Mov ax,AH |001AH| 000H|
|Mov bx,0026H| 001AH |0026H|
|Add al,bl |0040H| 0026H|
|Add ah,bl |2640H |0026H|
|Add bh,al |2640H| 4026|
|Mov ah,0 |0040H |4026H|
|Add al,85H| 00C5H| 4026H|
|Add al,93H |详细见下| 4026H|
程序段中最后一条指令为add al,93H ,在执行前,al中的数据为C5H ,相加后所得值为:158H,
但是al为8位寄存器,只能存放俩位十六进制的数据,所以最高位的1丢失,ax在的数据位:0058H(这里的丢失是因为进位值无法保存在8位寄存器中了,并不是CPU真的丢弃这个进位值)
!!!!此时al是作为一个独立的8位寄存器来使用的,和ah没有关系,CPU在执行这条指令时认为ah和al是二个不相关的寄存器,不要错误的认为,例如 add al,93H的值会进位到ah寄存器中,add al,93H进行的只是8位运算。 在进行数据传送或运算时,要注意指令的二个操作对象的位数应当为是一致的
物理地址
我们都晓得,CPU访问内存单元时,要给出内存单元的地址,所有的内存单元构成存储空间是一个一维的线性空间,每一个内存单元在这个看都有唯一的地址,就像IP一样 CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址,在CPU向地址总线发送物理地址前,必须要在内部先形成这个物理地址,不同的CPU可以有不同的形成物理地址的方式
三级标题16位结构的CPU
我们说的8086CPU的上一代CPU(8080,8085)都是8位机,而8086是16位机,也可以说8086是16位结构的CPU,那么什么是16位结构的CPU呢????
- 运算器一次可以处理16位的数据
- 寄存器最大宽度为16位
- 寄存器和运算器之间的通路为16位
- 8086CPU是16位结构的CPU,也就是说,在8086内部,能够一次性处理、传输、暂时存储的信息的最大程度是16位
- 内存单元的地址送上地址总线之前,必须在CPU中处理、传输、暂时存放,对于16位的CPU能在CPU中处理、传输、暂时存放16位的数据*
三级标题8086CPU给出物理地址的方法
8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力,从8086CPU的内部结构来看,如果地址简单从内部发出,那么只能送出去16位的地址,表现出的寻址能力就只有64KB。
·8086CPU采用一种在内部用二个16位地址合成的方法来形成一个20位的物理地址
当8086CPU要读写内存的时候:
- CPU中相关部件提供两个16位的地址,一个称为段地址,一个称为偏移地址
- 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件
- 地址加法器将这两个16位地址合成一个20位的物理地址
- 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
- 输入输出控制电路将20位物理地址送上地址总线
- 20位物理地址被地址总线传送到存储器
地址加法器采用物理地址=段地址x16+偏移地址的方法将段地址和偏移地址和成物理地址
比如8086CPU要访问地址为123C8H的单元地址,此时地址加法器工作原理
** 关于段地址x16的讨论** 段地址x16还有一个说法就是左移4位(指的是二进制位)
有一个例子,一个数据为2H,二进制形式为10B,对其进行左移运算 ::: tip 这里是博客技术原因,无法显示列表第四列,凑合看吧 左移位数 二进制 十六进制 十六进制 0 10B 2H 2 1 100B 4H 4 2 1000B 8H 8 3 10000B 10H 16 4 100000B 20H 32 :::
我们不难发现上面的次数和各位数的关系 一个二进制数据左移一位 结果乘以二 一个二进制数据左移N位,结果乘以N 地址加法器如何完成段地址x16的计算?那就是将二进制存放的数据左移4位
一个16进制的数据左移一位,相当于乘以16,一个十进制的数据左移一位,相当于乘以10,一个X进制的数据,左移一位,相当于乘以X。
“段地址x16+偏移地址=物理地址”得本质含义
这里,说的是8086CPU段地址和偏移地址得本质含义,而不是为了解决具体问题而在本质含义上引申出来的更高级得逻辑意义,“段地址x16+偏移地址=物理地址”得本质含义 “段地址x16+偏移地址=物理地址”得本质含义是:CPU在访问内存的时候,用一个基础地址(段地址x16)和一个相对于基础地址得偏移地址相加,给出内存单元的物理地址 修改CS、IP的指令 在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的额内容实现对CPU的控制。CPU从何处执行指令是由CS、IP中的内容决定的,程序员可以通过改变CS、IP的内容来控制CPU执行目标指令
如mov ax,123将ax中的值设为123,显然,我们也用同样得方法设置其他得寄存器得值,mov bx,123,mov cx,123,mov dx,123等等,大部分寄存器中得值都可以用mov指令来改变,所以mov指令被称为传送指令。
但是,mov指令不能用于设置CS、IP得值,原因很简单,因为8086CPU没有提供这样得功能。8086CPU为CS、IP提供了另外得指令来改变他们得值,能够改变CS、IP的内容的指令被称为转移指令
若要修改IP地内容,可用形如“jmp 某一合法寄存器” 的指令完成,如: jmp ax, 指令执行前: ax=1000H,CS=2000H,IP=0003H 指令执行后:ax=1000H,CS=2000H,IP=1000H
jmp bx, 指令执行前: bx=0B16H,CS=2000H,IP=0003H 指令执行后:bx=0B16H,CS=2000H,IP=0B16H
“jmp 某一合法寄存器”指令的功能为:用寄存器中的值修改IP
jmp ax,在含义上好似:mov IP,ax 把当前ax寄存器里的值赋值给IP寄存器(这只是用汇编语法解释新汇编指令,而不是说mov IP,ax真的有同jmp ax,一样的功能)
代 码 段 前面提到了,对于8086PC,在编程时,可以根据需要,见一组内存单元定义为一个段,可以将长度为N(小于等于60KB)的一组代码,存在一组地址连虚、起始地址为16倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,是一个代码段,它的段地位为123BH,长度为10个字节
如何让代码段中的指令被执行呢,将一段内存当作代码段,仅仅是我们在编程时的一种安排,CPU并不会由于这种安排,就自动的将我们定义的代码段中的指令当作指令来执行,CPU只认被CS:IP指向的内存单元中的内容为指令,所以,要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址,对于上面的例子,我们将一段代码存放在123B0H~123B9内存单元中,将其定义为代码段,如果要让这段代码执行,可设定:CS=123BH,IP=0000H
小 结
段地址在8086CPU的段寄存器中存放,当8086CPU要访问内存时,由段寄存器提供内存单元的段地位,8086有四个段寄存器,其中CS用来存放指令的段地址 CS中存放指令的段地址,IP存放指令的偏移地址。
8086机种,任意时刻,CPU将CS:IP指向的内容当作指令执行 3. 8086CPU的流程: 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器; IP指向下一条指令 执行指令(跳到第一步,重复过程) 4. 8086CPU提供转移指令修改CS:IP中的内容