汇编 - 寄存器

前言

  本文描述的为8086CPU.  在CPU中, 寄存器暂存一到二个字节的数据, 交于运算器进行信息处理, 值得注意的是, 真正存储数据的是内存, 寄存器起快速转移的作用.

1. 寄存器概述

8086CPU有14个寄存器, 都为16位寄存器, 分别为:

  1. 通用寄存器: AX, BX, CX, DX
    • AX(accumulator 累加寄存器), 用于一般的运算, 可分为两个8位寄存器AH(High 高八位), AL(low 低八位), 同时这两个寄存器也涉及中断指令的操作
    • BX(base 基址寄存器), 主要用于涉及内存地址和数组的运算, 可分为BH, BL两个8位寄存器
    • CX(count 计数寄存器), 是循环计数器, 也涉及位运算的使用, 可分为CH, CL两个8位寄存器
    • DX(data segment数据寄存器), 涉及内存地址的运算和指定I/O端口号, 可分为DH, DL两个8位寄存器

  1. 段寄存器: CS, DS, SS, ES
    • CS(code segment 代码段寄存器), 存储代码段的段地址, 和IP联合使用, 指明下一条执行的指令的位置
    • DS(data segment 数据段寄存器), 存储数据段的段地址
    • SS(stack segment 堆栈段寄存器), 存储堆栈段的段地址
    • ES(extra segment 附加段寄存器), 存储附加段的段地址, 附加段为一个额外的段, 配合其他段寄存器使用

  1. 指令指针寄存器: IP
    • IP(instruction pointer 指令指针寄存器), 存储代码段的偏移地址

  1. 指针和变址寄存器: SI, DI, SP, BP
    • SI(source index 源索引寄存器), 主要用于存储源数据的偏移地址
    • DI(destination index 目的索引寄存器), 主要用于存储目的数据的偏移地址
    • SP(stack pointer 堆栈指针寄存器), 主要用于指示堆栈的栈顶位置, 它存储的是偏移地址
    • BP(Base Pointer 基址指针寄存器), 主要用于配合SS访问堆栈不同位置, 而无需修改SP, 它存储的是偏移地址

  1. 标志寄存器: FLAGS
    • FLAGS(flags 标志寄存器), 包含9个标志位, 7个无意义位置, 即9 + 7 = 16位寄存器, 标志位用于条件的判定

以上主要为规范, 而非规则, CS和IP除外

2. 数据的存储

   一个字节由8个bit组成, 可以存储在8位寄存器中; 一个字由两个字节组成, 这两个字节分别称为这个字的高位字节和低位字节. 自然而然地, 若一个16位数据存在AX中, 其高八位存放在AH中, 低八位存放在AL中, 其他通用寄存器亦然

  一个内存单元可放8位数据, 寄存器又可放8或16位数据, 故用十六进制可直观看出某个数据有哪些八位数据构成; 如20000可写出4E20, 将其存放在AX中, 自然AH中为4E, AL中为20

  小心的是, 寄存器中数据最高位若是进位, 则不能保存, 无论是8位寄存器还是16寄存器

  另外, 值得注意的是, 二进制数据后加B, 十进制数据其后不加, 十六进制后加H

3. 16位结构CPU

16位CPU具有以下结构特性:

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

对于16位CPU而言, 能一次性处理、传输、暂时存储16位的地址

4. 物理地址

  CPU访问内存单元时, 需给出内存单元的地址, 这个唯一的地址称为物理地址。CPU向地址总线发出物理地址前, 必须要在内部先形成这个物理地址。

8086CPU有20位地址总线, 达到 2 20 2^{20} 220B, 即1MB的寻址能力, 但8086CPU又是16位结构, 表现的寻址能力只有 2 16 2^{16} 216B, 即64KB。故其通过左移4位的方式,获得20位地址, 以下进行说明:

  1. CPU中的相关部件提供两个16位地址, 一个称为段地址, 另一个称为偏移地址
  2. 段地址和偏移地址通过内部总线送入地址加法器
  3. 地址加法器将段地址左移4位, 再将其和偏移地址相加, 合成为一个20位的物理地址
  4. 地址加法器通过内部总线将20位的物理地址送入输入输出控制电路
  5. 输入输出控制电路将20位物理地址送入地址总线
  6. 地址总线将20位物理地址送入存储器, 即内存
    地址加法器采用段地址 × \times × 2 4 2^4 24 + 偏移地址 = 物理地址的方式合成物理地址,

以图说明

16位段地址
16位偏移地址
20位物理地址
20位物理地址
数据总线
控制总线
CPU
地址加法器
输入输出控制电路
内存

基于这种寻址方式, 我们采用分段的方式管理内存, 以段地址为一个段的起始地址, 以偏移地址定位段中的内存单元。值得注意的是,段地址由于需乘以16,故起始地址必然为16的倍数;同时偏移地址为16位数据, 故大小范围为0~ 2 16 2^{16} 216 - 1, 所以一个段的长度最大为 2 16 2^{16} 216B, 即64KB

5. 段寄存器

 存放段地址的寄存器称为段寄存器

5.1 CS和IP

  CS和IP是8086CPU中两个最关键的寄存器, 它们指明了CPU当前读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器

  任何时刻,若设CS中的内容为M,IP中的内容为N,则CPU将从内存M × 16 + N单元开始,读取指令并执行

5.2 修改CS、IP的指令

CS和IP不能直接修改,必须使用jmp(jump 跳跃)指令, jmp指令分为:

  • jmp 段地址 : 偏移地址, 用指令给出的段地址修改CS, 同时用给出的偏移地址修改IP
  • jmp 寄存器, 只用给出的数据修改IP

值得注意的是, 每执行一条指令, IP会自加一

5.3 代码段

  内存中存放运行代码的段,称为代码段
  值得注意的是,CPU只认被CS:IP指向的内容作为指令,所以需要将其指向代码段的第一行指令

6. debug调试

  debug是DOS、Windows 都提供的实模式程序的调试工具。使用它,可以查看CPU各种寄存器中的内容、内存的情况
常用的debug功能:

  • R命令,查看、修改CPU寄存器的内容
  • D命令,查看内存中的内容
  • E命令,改写内存中的内容
  • U命令,将内存中的机器指令翻译为汇编指令
  • T命令,单步执行一条机器指令
  • A命令,其后添加汇编指令时,将写入到内存

以下进行说明

使用 r 命令

r命令是 register 的缩写。这个命令用于显示和修改 CPU 寄存器的内容。

  1. 显示寄存器
    输入 r后按回车键,可以显示当前所有的 CPU 寄存器及其内容。输出通常包括通用寄存器(如 AX、BX、CX、DX 等)、段寄存器(如 CS、DS、ES 等)、指令指针(IP)和标志寄存器(FLAGS)等。

    示例:

    -r
    AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
    DS=1234  ES=5678  SS=9ABC  CS=DEF0  IP=0100   NV UP EI PL NZ NA PO NC
    
  2. 修改寄存器
    输入 r 后跟上寄存器名称,可以查看或修改该特定寄存器的值。例如,输入 r ax会提示你输入新的 AX 寄存器值。

    示例:

    -r ax
    AX 0000
    :1234
    

    上述例子中,输入 1234 将 AX 寄存器的值修改为 1234

使用 d 命令

d 命令是 dump 的缩写。这个命令用于显示指定内存地址范围的内容。

  1. 显示内存内容

    输入 d 后跟上一个起始地址,可以查看从该地址开始的内存内容。默认情况下,如果不指定地址,则从当前的指令指针(IP)所在位置开始显示。

    示例:

    -d 0100
    0A2B:0100  4D 5A 90 00 03 00 00 00-04 00 00 00 FF FF 00 00   MZ..............
    0A2B:0110  B8 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    0A2B:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    

    上述命令会显示从内存地址 0100 开始的内容,按 16 字节一行进行输出。

  2. 连续显示内存内容

    每次执行 d 命令后,可以通过再次输入 d 而不带参数,继续从上次显示结束的位置开始显示内存内容。

    示例:

    -d
    0A2B:0130  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    

使用 e 命令

e 命令是 enter 的缩写。这个命令用于在指定的内存地址处写入数据。

  • 写入数据到指定内存地址

    你可以使用 e 命令加上一个起始地址,然后依次输入你要写入的数据。数据可以是字符或十六进制数。

    示例:

    -e 0100
    0A2B:0100  00.41 00.42 00.43 00.44 00.45 00.46 00.47
    

    上述命令将数据 41 42 43 44 45 46 47(分别对应 ASCII 字符 A B C D E F G)写入从内存地址 0100 开始的地方。

使用 u 命令

u 命令是 unassemble 的缩写。这个命令用于将机器语言指令转换成汇编语言指令。

  1. 反汇编指定内存地址的内容

    输入 u 后跟上一个起始地址和一个结束地址,可以将这段内存中的机器语言指令转换成汇编语言指令。

    示例:

    -u 0100 0109
    0A2B:0100  B8 00 00 00 00 00 00 00-00 00                     .........
    0A2B:010A  CD 20                                             . 
    

    上述命令会将从内存地址 0100 到 0109 的内容转换为相应的汇编语言指令。

  2. 连续反汇编指令

    每次执行 u 命令后,可以通过再次输入 u 而不带参数,继续从上次转换结束的位置开始进行反汇编。

    示例:

    -u
    0A2B:0110  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    0A2B:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    

    上述命令会从上次 u 命令结束的位置开始继续反汇编内存内容。

使用 t 命令

t 命令是 trace 的缩写。这个命令用于单步执行一条机器指令,方便用户逐条检查程序的执行情况。

  1. 单步执行

    输入 t 命令后,debug 工具会执行当前指令,并显示下一条将要执行的指令。

    示例:

    -t
    AX=0000  BX=0000  CX=0000  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
    DS=0A2B  ES=0A2B  SS=0A2B  CS=0A2B  IP=0103   NV UP EI PL NZ NA PO NC
    0A2B:0103  CD 20        INT 20
    
  2. 连续单步执行

    可以多次输入 t 命令来逐条执行程序中的每一条指令。每次执行 t 后,debug 会更新寄存器和指令指针的状态,让你看到下一条指令。

    示例:

    -t
    AX=0201  BX=0000  CX=0000  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
    DS=0A2B  ES=0A2B  SS=0A2B  CS=0A2B  IP=0105   NV UP EI PL NZ NA PO NC
    0A2B:0105  <next instruction>
    

    执行完 t 命令后可以继续查看下一条指令及其影响。

使用 a 命令

a 命令是 assemble 的缩写。这个命令用于将汇编语言指令转换成机器语言指令,即将人类可读的汇编代码转换为计算机可以执行的二进制指令。

  1. 汇编指令

    输入 a 后跟上要汇编的一行汇编指令,debug 工具会将它转换为机器语言指令并写入内存。

    示例:

    -a 0100
    MOV AX, 0201
    

    上述命令将汇编代码 MOV AX, 0201 转换成相应的机器语言指令,并将其写入内存地址 0100 处。

  2. 连续汇编指令

    可以多次输入 a 命令来连续汇编多行汇编指令。每次执行 a 后,debug 会将汇编指令转换为机器语言指令并写入内存的下一个地址。

    示例:

    -a 0100
    MOV AX, 0201
    
    -a
    INT 20
    

    在这个例子中,第一个 a 命令将汇编指令 MOV AX, 0201 转换成机器语言指令并写入内存地址 0100。接下来的 a 命令将汇编指令 INT 20 转换成机器语言指令并写入内存的下一个地址。

总结

  • CPU可以用不同的段地址和偏移地址形成同一个物理地址
  • 若给定一个段地址, 仅通过变化偏移地址来寻址, 可寻址64KB
  • CS:IP指定执行中的指令
  • 地址加法器采用段地址 × \times × 2 4 2^4 24 + 偏移地址 = 物理地址的方式,合成物理地址

还请大家动动发财的小手, 给我点点赞, 蟹蟹

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值