最近在学习 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 | ? 显示 Debug 命令列表。 |
寄存器组
通用寄存器
通用寄存器
- 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 | OF(ov/nv):Over 溢出 标志位 溢出 OV(overflow溢出) NV(no overflow未溢出) |
- 进位标志CF(Carry Flag)
- 作用:当运算结果的最高有效位有进位(加法)或借位(减法)时,进位标志置1,即CF = 1;否则CF = 0。
1 | -u 100 |
可以看到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的结果
- 作用:运算结果二进制最高位为1,则SF = 1;否则SF = 0.
- 奇偶标志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
2mov ax,[2000]; ax-ds:[2000]
;从默认的DS数据段取出数据采用段超越前缀的指令实例:
1
2mov ax,ES:[2000]; dx-es:[2000]
;从指定的ES附加段取出数据
存储器分段
8086对逻辑段要求:
- 段地址低4位均为0
- 每段最大不超过64KB
8086对逻辑段并不要求:
- 必须是64kB
- 各段之间必须完全分开