汇编语言学习笔记(二):寄存器

学习参考:汇编语言(第2版)王爽

  • 通用寄存器
  • 字在寄存器中的存储
  • 几条汇编指令
  • 物理地址
  • 16 位结构的 CPU
  • 8086CPU 给出物理地址的方法
  • “段地址*16+偏移地址=物理地址” 的本质含义
  • 段的概念
  • 段寄存器
  • CS 和 IP
  • 修改 CS、IP 的指令
  • 代码段
  • 小结

一个典型的 CPU 由元算器、控制器、寄存器等器件构成,这些器件靠内部总线相连。在 CPU 中:

  • 运算器进行信息处理
  • 寄存器进行信息存储
  • 控制器控制各种器件进行工作
  • 内部总线连接各种器件,在它们之间进行数据的传送

8086CPU 有 14 个寄存器,每个寄存器有一个名称。这些寄存器是:
AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW

通用寄存器

8086CPU 的所有寄存器都是 16 位的,可以存放两个字节。AX、BX、CX、DX 这 4个存储器通常用来存放一般性到的数据,被称为通用寄存器

一个 16 位寄存器可以存储一个 16 位的数据。8086CPU 的 AX、BX、CX、DX 这 4 个寄存器都可分为两个可独立使用的 8 位寄存器来用:

  • AX 可分为 AH 和 AL
  • BX 可分为 BH 和 BL
  • CX 可分为 CH 和 CL
  • DX 可分为 DH 和 DL

以 AX 为例, 8086CPU 的 16 位寄存器分为两个 8 位寄存器的情况

AX 的低 8 位 (0位 ~ 7位)构成了 AL 寄存器, 高 8 位(8位 ~ 15位)构成了 AH 寄存器。AH 和 AL 寄存器可以独立使用的 8 位寄存器。下图为 16位寄存器及它所分成的两个 8 位寄存器的数据存储的情况,在 AH 中存储了它的高 8 位,在 AL 中存储了它的低 8 位。

字在寄存器中的存储

8086CPU 可以一次性处理以下两种尺寸的数据

  • 字节:记为 byte,一个字节由 8 个 bit 组成,可以存在 8 位寄存器中
  • 字:记为 word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节

一个字可以存在一个 16 位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高 8 位寄存器和低 8 位寄存器中

几条汇编指令

通过汇编指令控制 CPU 进行工作

汇编指令举例

汇编指令 控制 CPU 完成的操作 用高级语言的语法描述
mov ax,18 将 18 送入寄存器 AX AX=18
mov ah,78 将 78 送入寄存器 AH AH=78
add ax,8 将寄存器 AX 中的数值加上 8 AX=AX+8
mov ax,bx 将寄存器 BX 中的数据送入寄存器 AX AX=BX
add ax,bx 将 AX 和 BX 中的数值相加,结果存在 AX 中 AX=AX+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 044cH 8226H

因为 8226H + 8226H = 1044CH ,但是 ax 为 16 位寄存器,只能存放 4 位十六进制的数据,所以最高位的 1 不能在 ax 中保存, ax 中的数据为: 044CH

在对 al, ah 进行操作时,注意,此是 al 是作为一个独立的 8 位寄存器来使用的,和 ah 没有关系, CPU 在执行这条指令时认为 ah 和 al 是两个不相关的寄存器,如果操作数超过范围则高位会丢失

在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的

物理地址

CPU 访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址
CPU 通过地址总线送入存储器的,必须是一个内存单元的物理地址。在 CPU 想地址总线上发出物理地址之前,必须要在内部先形成这个物理地址

16 位结构的 CPU

16 位结构描述了一个 CPU 具有下面几方面的结构特性:

  • 运算器一次最多可以处理 16 位的数据
  • 寄存器的最大宽度为 16 位
  • 寄存器和运算器之间的通路为 16 位

在 8086 内部, 一次性处理、传输、暂时存储的信息的最大长度是 16 位的

8086CPU 给出物理地址的方法

8086CPU 有 20 位地址总线,可以传送 20 位地址,达到 1MB 寻址能力。8086CPU 是 16 位结构的, 一次性处理、传输、暂时存储的信息的最大长度是 16 位的。从内部结构看,如果将地址从内部简单地发出,那么它只能送出 16 位的地址,表现出的寻址能力只有 64 KB

8086CPU 采用一种在内部用两个 16 位地址合成的方法来形成一个 20 位的物理地址

  1. CPU 中的相关部件提供连两个 16 位的地址,一个称为段地址,一个称为偏移地址
  2. 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件
  3. 地址加法器将两个 16 位地址合成为一个 20 位的物理地址
  4. 地址加法器通过内部总线将 20 位物理地址送入输入输出控制电路
  5. 输入输出控制电路将 20 位物理地址送上地址总线
  6. 20 位物理地址被地址总线送到存储器

地址加法器采用 物理地址=段地址*16+偏移地址 的方法用段地址和偏移地址合成物理地址。

一个十六进制的数据左移 1 位,相当于乘以 16
一个 X 进制的数据左移 1 位,相当于乘以 X

“段地址*16+偏移地址=物理地址” 的本质含义

CPU 在访问内存时,用一个基础地址(段地址*16)和一个相对于基础地质的偏移地址相加,给出内存单元的物理地址

段的概念

内存并没有分段,段的划分来自于 CPU,我们可以用分段的方式来管理内存

地址 10000H ~ 100FFH 的内存单元组成一个段,该段的起始地址为 10000H,段地址为 1000H 大小为 100H

注意

  • CPU 可以用不同的段地址和偏移地址形成同一个物理地址
  • 偏移地址 16 位,变化范围为 0~FFFFH,仅用偏移地址来寻址最多可寻 64KB 个内存单元

“数据在 21F60H 内存单元中” 的一般说法是:

  • 数据存在内存 2000:1F60 单元中
  • 数据存在内存的 2000 段中的 1F60 单元中

段寄存器

段地址在 8086CPU 的段寄存器中存放。8086CPU 有 4 个段寄存器:CS、DS、SS、ES。当 8086CPU 要访问内存时由这 4 个段寄存器提供内存单元的段地址

CS 和 IP

CS 和 IP 是 8086CPU 中两个最关键的寄存器,它们指示了 CPU 当前要读取指令的地址

  • CS : 代码段寄存器 (Code Segment register)
  • IP : 指令指针寄存器 (Instruction Pointer register)

在 8086CPU 机中,任意时刻,设 CS 中的内容为 M,IP 中的内容为 N,8086CPU 将从内存 M*16+N 单元开始,读取一条指令并执行。即任意时刻,CPU 将 CS:IP 指向的内容当作指令执行

8086CPU 的工作过程可以简要描述如下:

  1. 从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲器
  2. IP=IP+所都去指令的长度,从而指向下一条指令
  3. 执行指令。转到(1),重复这个过程

Q:CPU 根据什么将内存中的信息看作指令?
A:CPU 将 CS:IP 指向的内存单元中的内容看作指令,因为,在任何时候,CPU 将 CS、IP 中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。如果说,内存中的一段信息曾被 CPU 执行过的话,那么,它所在的内存单元必然被 CS:IP 指向过。

修改 CS、IP 的指令

在 CPU 中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对 CPU 的控制。CPU 从何处执行指令是由 CS、IP 中的内容决定的,程序员可以通过改变 CS、IP 中的内容来控制 CPU

8086CPU 大部分寄存器的值,都可以用 mov 指令来改变,mov 指令被称为传送指令

mov 指令不能用于设置 CS、IP 的值,因为 8086CPU 没有提供该功能

能够改变 CS、IP 的内容的指令被称为转移指令

一个简单的可以修改 CS、IP 的指令:JMP 指令。若想同时修改 CS、IP 的内容,可用形如

1
jmp 段地址:偏移地址

的指令完成。其功能为:用指令中给出的段地址修改 CS,偏移地址修改 IP

例如

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

若想仅修改 IP 的内容,可用形如

1
jmp 某一合法寄存器

的指令完成。其功能为:用寄存器中的值修改 IP

例如

1
2
3
4
5
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

举个不恰当的比喻,这有点类似于 mov IP,ax,当然这个指令是不存在的,不过可以这么理解

代码段

首先我们可以将长度为 N (N <= 64KB)的一组代码,存在一组地址连续、起始地址为 16 的倍数的内存单元中,可以认为这段内存是用来存放代码的,从而定义一个代码段。

那么如何使得代码段中的指令被执行?CPU 只认被 CS:IP 指向所定义的代码段中的第一条指令的首地址。所以,要让 CPU 执行我们放在代码段中的指令,必须要将 CS:IP 指向所定义的代码段中的第一条指令的首地址。比如代码段存放在 123B0H ~ 123B9H 的一组内存单元中,要让这段代码得到执行,可设 CS=123BH、IP=0000H

小结

  1. 段地址在 8086CPU 的段寄存器中存放。当 8086CPU 要访问内存时,由段寄存器提供内存单元的段地址。8086CPU 有 4 个段寄存器,其中 CS 用来存放指令的段地址
  2. CS 存放指令的段地址,IP 存放指令的偏移地址。8086 机中,任意时刻,CPU 将 CS:IP 指向的内容当作指令执行。
  3. 8086CPU 的工作过程:
    i. 从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲器
    ii. IP 指向下一条指令
    iii. 执行指令(转到步骤 i ,重复这个过程)
  4. 8086 提供转移指令修改 CS、IP 的内容
Author: Inno Fang
Link: http://innofang.github.io/2017/11/18/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%BA%8C%EF%BC%89%EF%BC%9A%E5%AF%84%E5%AD%98%E5%99%A8/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-ND 4.0 unless stating additionally.