0%

8086指令基础 - 寄存器

最近在学习 16位汇编编程,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习汇编开发的童鞋们提供一份参考。

运行环境:

  • 操作系统: Windows 10家庭版
  • 编译器:Windows XP Debug

8086寄存器

计算机的指令系统是指该计算机能够执行的全部指令的集合,每种计算机都有它支持的指令集合。16位8086指令系统是Intel 80x86系列微处理器指令系统的基础

debug使用

  • 何为Denug?
    Dubug是Window和Dos下都提供的实模式调试工具。
  • Debug的使用。
    cmd下Debug就可以进入调试,注意64位系统下已经没有Debug了,Xp下才有,并且Xp下面的Debug也是虚拟出来的。
  • Debug命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
? 显示 Debug 命令列表。 
a 汇编 8086/8087/8088 记忆码。
d 显示部分内存的内容。
c 比较内存的两个部分。
e 从指定地址开始,将数据输入到内存。
f 使用指定值填充一段内存。
g 运行在内存中的可执行文件。
h 执行十六进制运算。
i 显示来自特定端口的 1 字节值。
l 将文件或磁盘扇区内容加载到内存。
m 复制内存块中的内容
/n 为 l 或 w 命令指定文件,或者指定正在测试的文件的参数。
o 向输出端口发送 1 个字节的值。
p 执行循环、重复的字符串指令、软件中断或子例程。
q 停止 Debug 会话。
r 显示或改变一个或多个寄存器。
s 在部分内存中搜索一个或多个字节值的模式。
t 执行一条指令,然后显示所有寄存器的内容、所有标志的状态和 Debug 下一步要执行的指令的解码形式。
u 反汇编字节并显示相应的原语句。
w 将被测试文件写入磁盘。
xa 分配扩展内存。
xd 释放扩展内存。
xm 映射扩展内存页。
xs 显示扩展内存的状态。

寄存器组

通用寄存器

通用寄存器

  • 8086的16位通用寄存器是:
    • AX BX CX DX
    • SI DI BP SP
  • 其中前四个数据寄存器还可以分为高八位和低八位
    • AH BH CH DH
    • AL BL CL DL
  • 对其八位的操作,并不影响对象八位的数据

数据寄存器用来存放计算的结果和操作数,也可以存放地址

每个寄存器又用它们各自的专用目的

  • AX - 累加器,使用频度最高,用于算数、逻辑运算以及外设传递信息等
  • BX - 基址寄存器,常用作存放寄存器地址
  • CX - 计数器,作为循环和串操作等指令中隐含计数器
  • DX - 数据寄存器,长用来存放双字长数据的高16位,或存放外设端口地址

变址寄存器

变址寄存器常用于存储器寻址时提供地址

  • SI是源变址寄存器
  • DI是目的变址寄存器

串操作类指令中,SI和DI具有特别的功能

指针寄存器

  • 指针寄存器用于寻址内存堆栈内的数据
  • SP为堆栈指针寄存器,指示栈顶的偏移地址
  • SP不能用于其他目的,具有专用性
  • BP为基址指针寄存器,表示数据在堆栈段中的基地址
  • SP和BP寄存器与SS段寄存器联合使用以确定堆栈段中的存储单元地址

指令指针寄存器

  • 指令指针寄存器IP,指示代码段中指令的偏移地址
  • 它与代码段寄存器CS联用,确定下一条指令的物理地址
  • 计算机通过CS:IP寄存器来控制指令序列的执行流程
  • IP寄存器是专用寄存器

标志寄存器

  • 标志寄存器用于反映指令执行结果或控制指令执行形式
  • 8086处理器的各种标志形成了一个16位的标志寄存器flags

  • 状态标志
    作用:用来记录程序运行结果的状态信息,许多指令的执行都将相应地设置它。
    CF ZF SF PF OF AF
  • 控制标志
    作用:可由程序根据需要用指令设置,用于控制处理器执行指令的方式
    DF IF TF

标志寄存器各位实验

  • 首先先来介绍以下debug中各标志位的意义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
OF(ov/nv):Over  溢出 标志位           溢出               OV(overflow溢出)                NV(no overflow未溢出)

DF(dn/up):Direction 方向 标志位 方向 DN(Down减少) UP(UP增加)

IF(ei/di):Enable 允许中断 标志位 中断 EI(enable interrupt许可) DI(disable interrupt 禁止)

SF(ng/pl):Symbol 符号 标志位 符号位 NG(negative)负 PL(plus 正)


ZF(zr/nz):Zero 零 标志位 零位 ZF(zero等于零) NZ(no zero不等于零)

AF(ac/na):Auxiliary 辅助进位 标志位 辅助进位 AC(assistant carry进位) NA(no assistant carry 无进位)

PF(pe/po):Parity 奇偶 标志位 奇偶标志 PE(parity even偶) PO(parity odd奇)

CF(cy/nc):Carry 进位 标志位 进位 CY(carry Yes进位) NC(No carry无进位)

TF ( Trap Flag ) 追踪标志: 当追踪标志TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求。这种方式主要用于程序的调试。指令系统中没有专门的指令来改变标志位TF的值,但程序员可用其它办法来改变其值。

  • 进位标志CF(Carry Flag)
    • 作用:当运算结果的最高有效位有进位(加法)或借位(减法)时,进位标志置1,即CF = 1;否则CF = 0。
1
2
3
4
5
-u 100
0B26:0100 B444 MOV AH,44
0B26:0102 B7FF MOV BH,FF
0B26:0104 01D8 ADD AX,BX
0B26:0106 C3 RET

可以看到Debug中最后一位由NC变为了CY,表示了计算结果进位;

  • 零标志ZF(Zero Flag)
    • 作用:若运算结果为0,则ZF = 1;否则ZF = 0

可以看到Debug中的ZF标志位由NC变为ZR,表示指令计算结果为0.

  • 符号标志SF(Sign Flag)
    • 作用:运算结果二进制最高位为1,则SF = 1;否则SF = 0.
      Debug中进行实验,计算4000+4000的结果

  • 奇偶标志PF(Parity Flag)
    • 作用:当运算结果最低字节中“1”的个数为零或偶数时,PF = 1;否则PF = 0

Debug中进行实验,计算3A+7A的值。

由于3AH+7AH=B4H=10110100B,二进制中总共有4个1,所以为偶数个1,奇偶标志位PF由PO变为PE

  • 溢出标志OF(Overflow Flag)

    • 作用:若算术运算的结果有溢出,则OF=1;否则 OF=0

    由于计算结果最高位为1,计算结果为负数明显是错误的结果,产生溢出,OF标志位由NV变为OV

  • 辅助进位标志AF(Auxiliary Carry Flag)
    • 作用:运算时D3位(低半字节)有进位或借位时,AF = 1;否则AF = 0。

由于低半字节存在进位,所以AF标志位由NA变为了AC

  • 方向标志DF(Direction Flag)
    • 作用:用于串操作指令中,控制地址的变化方向
      设置DF=0,存储器地址自动增加;
      设置DF=1,存储器地址自动减少。

输入指令CLD(复位指令),输入STD(置位指令)

可以观察出CLD将DF标志位置为UP,而STD将DF标志位置为DN

  • 中断允许标志IF(Interrupt-enable Flag)
    • 作用:用于控制外部可屏蔽中断是否可以被处理器响应:
      设置IF=1,则允许中断;
      设置IF=0,则禁止中断。

Debug中进行实验,输入指令CLI(中断复位指令),输入STI(中断置位指令)

可以观察出CLI将IF标志位置为DI,而STI将ID标志位置为EI

  • 陷阱标志TF(Trap Flag)
    • 作用:用于控制处理器进入单步操作方式:
      设置TF=0,处理器正常工作;
      设置TF=1,处理器单步执行指令。
  • 进位和溢出的区别

溢出标志OF和进位标志CF是两个意义不同的标志

  • 进位标志表示无符号数运算结果是否超出范围,运算结果仍然正确;
  • 溢出标志表示有符号数运算结果是否超出范围,运算结果已经不正确。

段寄存器

  • 8086CPU有20条地址线
    • 最大可寻址空间位x^2^ = 1MB
    • 物理地址范围从00000H~FFFFFH
  • 8086CPU将1MB空间分成许多逻辑段(Segment)
    • 每个段最大限制为64KB
    • 段地址的低四位为0000B
  • 一个逻辑存储单位将具有一个唯一的物理地址外,还具有多个逻辑地址

物理地址与逻辑地址

  • 对应每个物理存储单元都有一个唯一的20位编号,就是物理地址,从00000H~FFFFFH。
  • 分段后在用户编程时,采用逻辑地址,形式为:
    • 段基地址:段内偏移地址

cs:ip ==> 20位物理地址

cs<<4 + ip //cs左移四位+偏移

段寄存器和逻辑段

  • 8086有4个16位段寄存器
    • CS(代码段)指明代码段的起始位置
    • SS(堆栈段)指明堆栈段的起始地址
    • DS(数据段)指明数据段的起始地址
    • ES(附加段)指明附加段的起始地址
  • 每个段寄存器用来确定一个逻辑段的起始地址,每种逻辑段均有各自的用途

段超越前缀

  • 没用段超越前缀的指令实例:

    1
    2
    mov ax,[2000];			ax-ds:[2000]
    ;从默认的DS数据段取出数据
  • 采用段超越前缀的指令实例:

    1
    2
    mov ax,ES:[2000];		dx-es:[2000]
    ;从指定的ES附加段取出数据

存储器分段

  • 8086对逻辑段要求:

    • 段地址低4位均为0
    • 每段最大不超过64KB
  • 8086对逻辑段并不要求:

    • 必须是64kB
    • 各段之间必须完全分开