美文网首页
汇编(三)

汇编(三)

作者: 林大鹏 | 来源:发表于2017-07-12 17:31 被阅读55次

一. 8086的寻址方式

  • CPU访问内存单元是,要给出内存单元的地址,所有的内存单元都有唯一的地址,叫做物理地址

  • 808620条地址总线,可以传送20位的地址,1M的寻址能力

  • 但它又是16位结构的CPU,它内部能够一次性处理、传输、暂时存储的地址为16位。如果将地址从内部简单地发出,那么它只能送出16位地址,表现出来的寻址能力只有64KB

8086采用一种在内部用216位地址合成的方法来生成120位的物理地址

8086物理地址合成方式.png

地址加法器采用物理地址 = 段地址 * 16 + 偏移地址的方法用段地址偏移地址合成物理地址。例如,8086CPU要访问地址为123C8H的内存单元,此时,地址加法器的工作过程如下:

地址加法器工作过程.png

同时观察下面地址:

image.png

结论: CPU可以用不同的段地址和偏移地址形成同一个物理地址
比如CPU要访问21F60H单元,则它给出的段地址SA偏移地址EA来满足SA*16+EA = 21F60H即可。

二. 内存分段管理

  • 8086是用基础地址(段地址*16) + 偏移地址 = 物理地址的方式给出物理地址

  • 为了方便开发,我们可以采取分段的方法来管理内存,比如:

image.png
  • 地址10000H~100FFH的内存单元组成一个段,该段的起始地址(基础地址)为10000H,段地址为1000H,大小为100H.

  • 地址10000H ~ 1007FH10080H ~ 100FFH的内存单元组成2个字段,他们的起始地址(基础地址)为:10000H和10080H,段地址为1000H1008H,大小都为80H.

  • 在编程时可以根据需要,将若干连续地址的内存单元看做一个段,用段地址*16定为段的起始地址(基础地址),用偏移地址定位段中的内存单元。

  • 段地址*16必然是16的倍数,所以一个段的起始地址(基础地址)也一定是16的倍数。

  • 偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB

练习:

1. 在8086中如果给定一个段地址,仅通过变换偏移地址来进行寻址,最多可定位多少个内存单元?

解答:
偏移地址为16位,变化范围是0x0000~0xFFFFH,仅用偏移地址来寻址最多可寻64KB个内存单元。比如给定段地址1000H,用偏移地址寻址,CPU的寻址范围为:10000H ~ 1FFFFH.

2. 在8086PC机中,存储单元的地址用两个元素来描述,即段地址和偏移地址。

“数据在21F60H内存单元中”,这句话对于8086PC机一般不这样将,取而代之的是两种类似的说法:

  • 数据存在内存2000:1F60单元中,
  • 数据存在内存的2000H段中的1F60H单元中。这两种描述都表示"数据在内存21F60H单元中"。

三. 段寄存器

  • 8086在访问内存是要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址。

  • 是什么部件提供段地址?段地址在8086的段寄存器中存放。

  • 80864个段寄存器: CS、DS、SS、ES、当CPU需要访问内存时由这4个段寄存器提供内存单元的段地址

  • CS (Code Segment): 代码段寄存器

  • DS (Data Segment): 数据段寄存器

  • SS (Stack Segment): 堆栈段寄存器

  • ES (Extra Segment): 附加段寄存器

四. CS和IP

  • CS代码段寄存器IP指令指针寄存器,它们指示了CPU当前要读取指令的地址。
  • 任意时刻,8086CPU都会将CS:IP指向的指令作为下一条需要取出执行的指令。
image.png

(1) 8086CPU当前状态: CS中的内容为2000H,IP中的内容为0000H;
(2) 内存20000H ~ 20009H 单元存放着可执行的机器码;
(3) 内存20000H ~ 20009H 单元中存放的机器码对应的汇编指令如下。
地址: 20000H ~ 20002H,内容: B8 23 01, 长度: 3Byte, 对应汇编指令: mov ax, 0123H;
地址: 20003H ~ 20005H, 内容:BB 03 00, 长度: 3Byte, 对应汇编指令: mov bx, 0003H;
地址: 20006H ~ 20007H, 内容: 89 D8, 长度: 2Byte, 对应汇编指令: mov ax, bx;
地址: 20008H ~ 20009H, 内容: 01 D8, 长度: 2Byte, 对应汇编指令: add ax, bx

五.指令执行过程

image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png

通过上面的过程展示,8086CPU的工作过程可以简要描述如下:

  1. CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器

2.IP = IP + 所读指令的长度,从而指向下一条指令。

  1. 执行指令。转到步骤1,重复该过程。

8086CPU加电启动或复位后(即CPU刚开始工作时)CSIP被设置为CS = FFFFH,IP = 0000H,即在8086PC机刚启动时,CPU从内存FFFF0H单元读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。

六.指令和数据

  • 在内存或者磁盘上,指令和数据没有任何区别,都是二进制信息。

  • CPU在工作的时候把有的信息看做指令,有的信息看做数据,为同样的信息赋予了不同的意义。

举个🌰 :
例如,内存中的二进制信息 1000 1001 1101 1000,计算机可以把它看做大小为89D8H的数据来处理,也可以看做指令mov ax, bx 来执行

1000 1001 1101 1000 -> 89D8H(数据)
1000 1001 1101 1000 -> mov ax, bx (程序)
  • CPU根据什么将内存中的信息看做指令:
  • CPUCS:IP指向的内存单元的内容看做指令
  • 如果内存中的某段内容曾被CPU执行过,那么它所在的内存单元必然被CS:IP指向过。

七. jmp指令

  • CPU从何处执行指定是由CS、IP中的内容决定的,我们可以通过改变CS、IP的内容来控制CPU执行目标指令。

  • 8086提供了一个mov指令(传送指令),可以用来修改大部分寄存器的值,比如 mov ax, 10; mov bx, 20; mov cx, 30; mov dx, 40

  • 但是,mov指令不能用于设置CS、IP的值,这些指令统称为转移指令、最简单的是jmp指令。
    举个🌰 :
    若想同时修改CS、IP的内容,可用形如"jmp 段地址: 偏移地址"的指令来完成。如:

    jmp 2AE3 : 3,执行后: CS = 2AE3H, IP = 0003H, CPU将从2AE33H处读取指令
    jmp 3:0B16, 执行后: CS = 0003H, IP = 0B16H, CPU将从 00B46H处读取指令。
    

** “jmp 段地址: 偏移地址” 指令的功能为: 用指令中给出的段地址修改CS, 偏移地址修改IP**。

若想仅修改IP的内容,可用形如"jum 某一合法寄存器" 的指令完成,如:

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

jum ax, 在含义上好似: mov IP, ax

八.jmp指令 --- 练习

第一题:

image.png

答案:
- mov ax, 6622H
- jmp 1000 : 3
- mov ax, 0000
- mov bx, ax
- jmp bx
- mov ax, 0123H
- 转到第3步执行

分析:

  • CPU初始状态: CS = 2000H, IP = 0000H,所以一开始寻址地址从2000H开始。执行mov ax, 6622H
  • 然后执行: jmp 1000:3,此时寻址地址是从10003H开始
  • 10003H执行 mov ax, 0000,这时候ax寄存器的值为0000
  • 然后执行 mov bx, ax,将ax的值赋值给bxbx寄存器的值为0000
  • 然后执行jmp bx,这时候寻址地址从10000H开始
  • 10000H执行mov ax, 0123H
  • 然后转到10003H重复 该流程

第二题:

image.png

答案:
CPU 4次修改IP
分别在:
mov ax, bx执行了一次
sub ax, ax执行了一次
jmp ax执行了两次,

最后IP中的值是0.
分析:

  • mov ax, bx ->将bx的值移到ax寄存器
  • sub ax, ax, -> 将ax寄存器中的值减去本身,所以ax寄存器中的值为0
  • jmp ax -> jmp 0,在这里修改了IP的值,IP的值为0.

九. 代码段

前面讲过,对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将长度为N(N小于等于64KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,从而定义了一个代码段。比如,将:

image.png

这段长度为10个字节的指令,存放在123B0H ~ 123B9H的一组内存单元中,我们就可以认为,123B0H~123B9H这段内存是用来存放代码的,是一个代码段,它的段地址为123BH,长度为10个字节。

如何使得代码段中的指令被执行呢?将一段内存当做代码段,仅仅是我们在编程时的一种安排,CPU并不会由于这种安排,就自动将我们定义的代码段中的指令当做指令来执行。CPU只认被CS:IP指向的内存单元中的内容为指令。所以要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段钟的第一条指令的首地址。对于上面的例子,我们将一段代码存放在123B0H ~ 123B9H 内存单元中,将其定义为代码段,如果要让这段代码得到执行,可设CS = 123BH,IP=0000H

相关文章

  • <安全攻防之汇编基础>

    &关于汇编基础请点击 <汇编一> <汇编二> <汇编三> <汇编四> <汇编五> <汇编六> <汇编七> <汇编八...

  • (二) LLDB理解汇编

    1. 汇编寄存器调用约定 1.1 汇编101 看看下面的汇编片段: 在这段汇编代码中有三个操作码pushq、sub...

  • 汇编(三)

    8086的寻址方式 CPU访问内存单元时,要给出内存单元的地址,所有的内存单元都有唯一的地址,叫做物理地址 808...

  • 汇编三

    完整的汇编指令:#### 汇编由两种指令组成1.汇编指令如mov、add、sub等有对应的机器指令,可以被编译为机...

  • 汇编(三)

    8086的寻址方式 CPU访问内存单元时,要给出内存单元的地址,所有的内存单元都有唯一的地址,叫做物理地址 808...

  • 汇编(三)

    一. 8086的寻址方式 CPU访问内存单元是,要给出内存单元的地址,所有的内存单元都有唯一的地址,叫做物理地址 ...

  • 汇编(三)

    1.函数的局部变量 定义一个局部变量c,断点查看汇编中c的存储调用 2.函数的嵌套调用 定义2个函数,funcA中...

  • 汇编(三)

    一. 函数的参数 1.1 多个参数创建空工程001--Demo,编写代码如下 test方法调用处打断点,运行工程断...

  • 汇编程序基础

    汇编程序基础 一、汇编程序基本结构 二、汇编指令 1.汇编指令基本结构 三、伪指令 1.段定义 2.数据定义 数据...

  • 提高代码执行效率的几个小技巧

    前言 目录 一、方法参数限制 二、反汇编 switch case & if else 三、C 中写汇编代码 四、 ...

网友评论

      本文标题:汇编(三)

      本文链接:https://www.haomeiwen.com/subject/eutbhxtx.html