8086 汇编学习 Part 2

寄存器及数据存储

CPU组成

  • 运算器进行信息处理
  • 寄存器进行信息存储
  • 控制器协调各种器件进行工作
  • 内部总线先实现 CPU 内各个器件之间的联系

寄存器

寄存器是 CPU 内部的信息存储单元。
8086 CPU 有 14 个寄存器:

  • 通用寄存器:AX, BX, CX, DX
  • 变址寄存器:SI,DI
  • 指针寄存器:SP,BP
  • 指令指针寄存器: IP
  • 段寄存器: CS, SS, DS, ES
  • 标志寄存器: PSW
    8086 CPU 所有的寄存器都是 16 位的,可以存放两个字节。

通用寄存器

一个 16 位寄存器存储一个 16 位的数据
每一位保存一个二进制位能保存的最大值为 2 16 − 1 2^{16} - 1 2161 (FFFFH)

如何兼容 8 位寄存器环境下编写的程序?

通用寄存器均可以分为两个独立的 8 位寄存器使用,AX 可以分为 AH 和 AL,BX, CX, DX 同理

“字”在寄存器中的存储

8086 是 16 位 CPU,字长 为 16 bit
一个可以存在一个 16 位寄存器中

  • 这个字的高位字节存在这个寄存器的高 8 位寄存器
  • 这个字的低位字节存在这个寄存器的低 8 位寄存器

mov指令

  • MOV (通用寄存器) , (数据)
  • MOV (寄存器) , (寄存器)
  • MOV (寄存器) , (内存单元)
  • MOV (内存单元) , (寄存器)
  • MOV (段寄存器) , (通用寄存器)
    汇编指令不区分大小写
    数值默认为 10 进制,写入 16 进制需在末尾添加 ‘H’
    在低位寄存器出现溢出时,不会进位到高位

确定物理地址的方法

CPU 访问内存单元时要给出内存单元的地址。
所有内存单元构成的存储空间是一个一维的线性空间。
每一个内存单元都有唯一的地址,叫物理地址
8086 有 20 位地址总线,可传送 20 位地址,寻址能力是 2 20 = 1 M 2^{20} = 1 M 220=1M
8086 是 16 位结构的 CPU,运算器一次最多处理 16 位的数据,寄存器的最大宽度为 16 位。
在 8086 内部处理的、传输、暂存的地址也是 16 位,寻址能力只有 64 KB

如何处理地址总线 20 位的寻址能力受限于 16 位地址长度这一问题?

用两个 16 位地址(段地址和偏移地址)合成一个 20 位的物理地址。
地址加法器合成物理地址的方法: 物理地址 = 段地址 ∗ 16 + 偏移地址 物理地址 = 段地址 * 16 + 偏移地址 物理地址=段地址16+偏移地址

内存的分段表示法

内存并没有分段,段的划分来自于 CPU
Assembly336b8fa9b12d81a3d.png
段地址 : 偏移地址
同一段内存可以有多种分段方案

  • 段地址 ∗ 16 段地址 * 16 段地址16 必然是 16 的倍数, 所以一个段的起始地址也一定是 16 的倍数。
  • 偏移地址为 16 位,16 位地址的寻址能力为 64K,所以一个段的长度最大为 64K。
  • 可以用不同的段地址和偏移地址形成同一个物理地址。
    8086 有丰富的取址方式,因此偏移地址可以用多种方法提供。

段寄存器

段寄存器存放段地址,段寄存器只能由寄存器赋值,不支持用字面值直接赋值。
8086 CPU 有 4 个段地寄存器

  • CS 代码段寄存器
  • DS 数据段寄存器
  • SS 栈段寄存器
  • ES 附加段寄存器

Debug

Debug 是 DOS 系统中著名的调试程序。
使用 Debug 程序,可以查看 CPU 各种寄存器中的内容、内存的情况,并且在机器指令级跟踪程序的运行。

常用 Debug 命令

  • R 命令 查看、改变 CPU 寄存器的内容
    -R 查看所有寄存器内容
    -R (寄存器名) (数据) 修改特定寄存器中的数据
  • D 命令 查看内存中的内容
    -D 列出预设地址内存处的 128 个字节的内容,每次偏移 128 个字节
    -D (段地址:偏移地址) 列出内存中指定地址处的内容
    -D (段地址:偏移地址) (结尾偏移地址) 列出内存中指定地址范围内的内容
  • E 命令 改变内存中的内容
    -E (段地址:偏移地址) (数据1) (数据2) … 改变内存中的内容
    -E (段地址:偏移地址) 逐个询问式修改,空格代表接受并继续回车代表修改结束
  • U 命令将内存中的机器指令翻译成汇编指令
    -U (段地址:偏移地址)
  • A 命令以汇编指令的格式在内存中写入机器指令
    -A (段地址:偏移地址) 逐行输入汇编指令
  • T 命令执行机器指令
    -T 执行 CS:IP 处的指令
  • Q 命令推出 Debug

CS、IP 与代码段

CPU 将内存中 CS:IP 指向的内容当作指令执行。

8086 读取和执行指令

  1. 从 CS:IP 指向内存单元读取指令,读取的指令进入指令缓冲器
  2. IP = IP + 所读指令的长度,从而指向下一条指令
  3. 执行指令,跳转到步骤 1
  4. 重复此过程

jmp 指令

执行何处的指令,取决于 CS:IP 指向的数据
可以通过改变 CS 和 IP 中的内容,来控制 CPU 要执行的目标指令
Bebug 可以改变 CS 和 IP 的值,但是 Debug 是调试手段,并非程序方式。
8086 CPU 不提供对 IP 修改的指令,不能使用 MOV 指令修改,只能由 CPU 自行修改
使用转移指令 jmp

  • jmp (段地址:偏移地址) 用段地址修改 CS ,偏移地址修改 IP
  • jmp (某一合法寄存器) 用某一合法寄存器的数据修改 IP

内存中”字“的存储

8086 CPU 中,16 位作为 1 个字。
16 位的字,高 8 位存放高字节,低 8 位存放低字节,从而实现存储在 1 个 16 位的寄存器中。

字单元

子单元由两个地址连续的内存单元组成,存放一个字型数据
在一个字单元中,低地址单元存放低位字节,高地址单元存放高位字节

用 DS 和 [addres] 实现字的传送

CPU 要读取一个内存单元的时候,必须给出这个内存单元的地址
在 8086 PC 中,内存地址由段地址和偏移地址组成(段地址:偏移地址)
用 DS 和 [address] 配合,用 DS 寄存器存放要访问的数据的段地址
偏移地址用 […] 形式给出
MOV 指令中,只写 [address] 时,默认段地址就是 DS 。

DS 和数据段

对内存单元中数据的访问

对于 8086 , 可以根据需要将一组内存单元定义为一个段

  • 物理地址 = 段地址 ∗ 16 + 偏移地址 物理地址 = 段地址 * 16 + 偏移地址 物理地址=段地址16+偏移地址
  • 将一组长度为 N ( N ≤ 64 K ) N(N \leq 64K) N(N64K) 、地址连续、起始地址为 16 的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
    用 DS 存放数据段的段地址,用指令访问数据段中的具体单元,单元地址由 [address]指出。

加法 add 和减法 sub 指令

  • add (寄存器) , (数据)
  • add (寄存器) , (寄存器)
  • add (寄存器) , (内存单元)
  • add (内存单元) , (寄存器)
    段寄存器不能作为被加数,add 指令的参数不能全为内存单元
  • sub (寄存器) , (数据)
  • sub (寄存器) , (寄存器)
  • sub (寄存器) , (内存单元)
  • sub (内存单元) , (寄存器)
    段寄存器不能作为被减数,sub 指令的参数不能全为内存单元

栈及栈操作的实现

栈是一种只能在一端进行插入或删除操作的数据结构。
栈有两个基本的操作

  • 入栈:将一个新的元素放到栈顶
  • 出栈:从栈顶取出一个元素
    栈顶元素总是最后入栈,需要出栈时,又最先被从栈中取出。
    栈的操作规则:LIFO (Last In First Out ,后进先出)
    CPU 提供的栈机制,支持用栈的方式访问内存空间,可以将一段内存当作栈来使用。
    PUSH (寄存器) 将寄存器中的数据送入栈,实质上就是一种内存传送指令,与 MOV 不同的是,PUSH 指令访问的内存单元的地址不作为参数,而是由 SS:SP 所指向的。
    POP (寄存器) 从栈顶取出数据送入寄存器,实质同 PUSH。
    栈顶寄存器 SS 存放栈顶的段地址,栈顶指针寄存器 SP 存放栈顶的偏移地址,
    SS:SP 任意时刻都指向栈顶元素

栈指令执行过程

  • PUSH (寄存器)
    1. SP = SP - 2
    2. 将寄存器中的内容送入 SS:SP 指向的内存单元处,SS:SP 此时指向新栈顶
  • POP (寄存器)
    1. 将 SS:SP 指向的内存单元处的数据送入寄存器中
    2. SP = SP + 2
    3. SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

栈顶越界问题

栈空时使用 POP 指令或栈满时使用 PUSH 指令,都会导致栈顶越界
8086 CPU 不保证对栈的操作不会越界,需要在编程时注意。

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值