汇编:标志寄存器、adc带进位加法指令、sbb带借位减法指令、cmp指令、DF标志和串传送指令
一、8086 标志寄存器的位分布可简化为下图:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
── ── ── ── ── DF IF TF SF ZF ── AF ── PF ── CF
(保留位) 控制标志 状态标志
二、标志寄存器分类
按功能分为状态标志(反映运算结果)、控制标志(控制 CPU 行为)、系统标志(特权级 / 系统相关),其中状态标志的别名是汇编调试 / 编程中最常用的,先汇总核心对应关系:
| 标志位类型 | 标准名称(缩写) | 位位置 | 常用状态别名(1/0) | 核心含义 |
|---|---|---|---|---|
| 状态标志 | 进位标志(CF) | 0 | CY(1)/ NC(0) | 无符号数运算进位(加法)/ 借位(减法) |
| 状态标志 | 奇偶标志(PF) | 2 | PE(1)/ PO(0) | 运算结果低 8 位 1 的个数:偶数(PE)/ 奇数(PO) |
| 状态标志 | 辅助进位(AF) | 4 | AC(1)/ NA(0) | 低 4 位(半字节)进位 / 借位(BCD 码运算专用) |
| 状态标志 | 零标志(ZF) | 6 | ZR(1)/ NZ(0) | 运算结果:0(ZR)/ 非 0(NZ) |
| 状态标志 | 符号标志(SF) | 7 | NG(1)/ PL(0) | 有符号数结果:负(NG,最高位 1)/ 正 / 0(PL,最高位 0) |
| 状态标志 | 溢出标志(OF) | 11 | OV(1)/ NV(0) | 有符号数运算:溢出(OV)/ 无溢出(NV) |
| 控制标志 | 陷阱标志(TF) | 8 | TR(1)/ NT(0) | 单步调试(TR)/ 正常执行(NT) |
| 控制标志 | 中断允许(IF) | 9 | EI(1)/ DI(0) | 允许可屏蔽中断(EI)/ 屏蔽中断(DI) |
| 控制标志 | 方向标志(DF) | 10 | DN(1)/ UP(0) | 字符串操作:反向(DN)/ 正向(UP) |
三、标志寄存器的访问方法
pushf:将标志寄存器的值压栈
popf:从栈中弹出数据,送入标志寄存器中
四、介绍各个主要的标志寄存器
4.1 ZF -零标志(Zero Flag)
1. 核心规则
当 CPU 执行算术运算(如 SUB、ADD)或逻辑运算(如 AND、XOR)后:
- 若运算结果 等于 0 → ZF = 1
- 若运算结果 不等于 0 → ZF = 0
注意:
- 运算结果是否为 0,是判断 ZF 的唯一标准,与运算类型无关。
- 数据传输类指令(如
MOV)不会修改 ZF,只有会改变运算结果的指令才会更新标志位。
4.2 PF-奇偶标志(Parity Flag)
1. 核心定义
当 CPU 执行算术运算、逻辑运算等指令后,会根据结果的低 8 位中二进制位为1的数量,设置 PF 的值:
- PF = 1:结果低 8 位中
1的个数为 偶数(0、2、4、6、8...) - PF = 0:结果低 8 位中
1的个数为 奇数(1、3、5、7...)
注意:PF 仅关注结果的低 8 位,即使运算结果是 32 位或 64 位,高位部分不影响 PF 的取值。
2. 工作原理示例
示例 1:逻辑运算(AND)
; 假设 AL = 0x03 (二进制 0000 0011)
AND AL, 0x05 ; 0000 0011 & 0000 0101 = 0000 0001 (结果 0x01)
运算结果低 8 位:0000 0001 → 其中1的个数 = 1(奇数)→ PF = 0
示例 2:算术运算(ADD)
; 假设 AL = 0x02 (二进制 0000 0010)
ADD AL, 0x04 ; 0000 0010 + 0000 0100 = 0000 0110 (结果 0x06)
运算结果低 8 位:0000 0110 → 其中1的个数 = 2(偶数)→ PF = 1
4.3 SF-符号标志(Sign Flag)
SF(Sign Flag,符号标志位)是 CPU 标志寄存器中的状态标志位,核心作用是反映算术 / 逻辑运算结果的符号属性,其值与运算结果的最高位完全一致,在有符号数运算中用于判断结果正负。
1.核心工作原理
- 取值规则:SF 的值直接等于运算结果的最高有效位(MSB)。在有符号数的二进制补码表示中,最高位为 1 表示负数,为 0 表示正数或零。
- 若运算结果为负,
SF=1; - 若运算结果为非负(正数或零),
SF=0。
- 若运算结果为负,
2.实际应用示例
以 x86 汇编的CMP指令(比较两个数,本质是执行减法运算)为例,SF 会配合其他标志位(如 OF 溢出标志)实现有符号数的条件跳转:
mov eax, 5 ; EAX = 5(00000101B)
mov ebx, 10 ; EBX = 10(00001010B)
cmp eax, ebx ; 执行EAX - EBX = -5(11111011B),SF=1(最高位为1)
js negative ; 若SF=1,跳转到negative标签处
上述代码中,cmp指令的结果为负,SF 被置 1,js(Jump if Sign)指令会检测到 SF=1 并执行跳转。
4.4 CF-进位标志(Carry Flag)
进位标志(CF) 是 CPU 状态寄存器(FLAGS/EFLAGS 寄存器)中的一个 1 位标志位,用于反映无符号数运算中最高位是否产生进位或借位,是底层汇编和计算机组成原理中处理数值溢出的核心标志之一。
1.核心作用
CF 的核心功能是标记 无符号数算术运算 的进位 / 借位状态,与用于有符号数溢出的溢出标志(OF) 是两个独立的概念,二者不可混淆。
- 加法运算(ADD/ADC):当两个无符号数相加,最高有效位(MSB) 产生向更高位的进位时,
CF = 1;否则CF = 0。 - 减法运算(SUB/SBB):当两个无符号数相减,被减数小于减数 导致需要向更高位借位时,
CF = 1;否则CF = 0。
2.原理与示例(以 8 位无符号数为例)
8 位无符号数的取值范围是 0 ~ 255(二进制 0000 0000 ~ 1111 1111)。
2.1. 加法进位场景
计算 250 + 10:
- 二进制表示:
1111 1010 + 0000 1010 = 1 0000 0100 - 运算结果:8 位寄存器只能存储低 8 位
0000 0100(对应十进制 4),最高位产生 1 个进位。 - 标志状态:
CF = 1,表示无符号数加法溢出。
2.2. 减法借位场景
计算 5 - 10:
- 无符号数减法本质是被减数 + 减数的补码:
0000 0101 + 1111 0110 = 1111 1011(对应十进制 251) - 运算逻辑:因为
5 < 10,需要向更高位借位才能完成减法,借位发生时 CF 置 1。 - 标志状态:
CF = 1,表示无符号数减法不够减。
2.3. 无进位 / 借位场景
计算 100 + 50 = 150:
- 二进制:
0110 0100 + 0011 0010 = 1001 0110 - 最高位无进位,
CF = 0。
4.5 OF-溢出标志(Overflow Flag)
溢出标志(OF)是 CPU 状态寄存器(FLAGS/EFLAGS/RFLAGS)中的一个核心标志位,用于检测有符号数算术运算的溢出,仅对有符号数运算有效;无符号数的溢出由进位标志(CF)检测,二者需严格区分。
1.核心定义
当有符号数的算术运算结果超出了该数据类型能表示的范围时,OF 置 1(溢出);否则置 0(无溢出)。
- 例如:8 位有符号数的取值范围是
[-128, +127],若运算结果超出此范围,OF=1; - 16 位有符号数范围:
[-32768, +32767],32 位:[-2^31, 2^31-1],以此类推。
4.6 DF-方向标志(Direction Flag)
DF(Direction Flag)是FLAGS 寄存器中的第 10 位,用于控制串操作指令(如串传送、串比较等)中地址指针(SI/DI)的变化方向,是串操作的核心控制位。
1. DF 的取值与作用
| DF 值 | 地址变化方向 | 说明 |
|---|---|---|
| 0(默认 / 清除) | 递增(↑) | 串操作时,SI/DI 自动 + 1(字节操作)或 + 2(字操作),向高地址处理 |
| 1(置位) | 递减(↓) | 串操作时,SI/DI 自动 - 1(字节操作)或 - 2(字操作),向低地址处理 |
2. 控制 DF 的指令
CLD(Clear Direction Flag):将 DF 置 0(地址递增),最常用。STD(Set Direction Flag):将 DF 置 1(地址递减)。
注:x86 汇编中,串操作默认使用 SI(源变址寄存器)指向源串,DI(目的变址寄存器)指向目的串(段默认:源串在 DS 段,目的串在 ES 段)。
3.串传送指令(MOVS)
MOVS(Move String)是专门用于批量传送内存数据的串操作指令,自动根据 DF 调整地址指针,配合重复前缀可实现连续数据块传送,效率远高于普通 MOV 指令。
指令格式(3 种等价形式)
| 格式 | 操作类型 | 功能说明 |
|---|---|---|
MOVSB | 字节传送 | ES:[DI] ← DS:[SI],然后 SI/DI ±1(由 DF 决定) |
MOVSW | 字传送(16 位) | ES:[DI] ← DS:[SI],然后 SI/DI ±2(由 DF 决定) |
MOVSD | 双字传送(32 位) | ES:[DI] ← DS:[SI],然后 SI/DI ±4(由 DF 决定) |
注:MOVS 指令本身不指定操作数(操作数由 SI/DI 隐含),也可写显式格式(如
MOVS ES:BYTE PTR [DI], DS:[SI]),但通常用 MOVSB/MOVSW/MOVSD 更简洁。
ES:[DI] ← DS:[SI] 核心含义
这是串操作指令(如 MOVSB/MOVSW/MOVSD)的核心数据传输逻辑,表示:
将「数据段(DS)中以源变址寄存器(SI)为偏移地址」的内存单元数据,赋值给「附加段(ES)中以目的变址寄存器(DI)为偏移地址」的内存单元。
拆解成更易理解的形式:
| 部分 | 含义 |
|---|---|
DS:[SI] | 源操作数:DS 是段寄存器(默认源串段),SI 是偏移地址,合起来指向源内存单元 |
ES:[DI] | 目的操作数:ES 是附加段寄存器(目的串固定段),DI 是偏移地址,指向目的内存单元 |
← | 数据流向:源单元的数据被复制到目的单元(源数据保留,目的数据被覆盖) |
assume cs:code ; 声明cs寄存器关联code段(仅编译提示,无执行逻辑)
data segment ; 数据段开始
db 'Welcome to masm!' ; 偏移0: 16字节字符串("Welcome to masm!" 恰好16个字符)
db 16 dup(0) ; 偏移16: 预留16字节空间,初始化为0
data ends ; 数据段结束
code segment ; 代码段开始
start: ; 程序入口标签
; 初始化段寄存器和指针
mov ax,data
mov ds,ax ; ds = 数据段段基址(8086不支持直接mov ds, 立即数,需通过ax中转)
mov si,0 ; ds:si 指向源地址(偏移0)
mov es,ax ; es = 数据段段基址(movsb使用es:di作为目的地址)
mov di,16 ; es:di 指向目的地址(偏移16)
cld ; 清除方向标志DF=0 → movsb执行后si/di自动+1(正向传送)
; 循环执行字节串传送
mov cx,16 ; 循环次数=16(字符串长度)
s: movsb ; 核心指令:将ds:si的1字节传送到es:di,然后si+1、di+1(因DF=0)
loop s ; cx-1,若cx≠0则跳回s标签
; 程序退出(DOS中断)
mov ax,4c00H ; 4cH号功能:程序退出,00H为返回码
int 21H ; 调用DOS中断,结束程序
code ends ; 代码段结束
end start ; 汇编结束,指定程序入口为start标签
关键知识点说明
| 指令 / 标志 | 作用 |
|---|---|
cld | 方向标志 DF=0 → movsb/movsw 执行后 si/di 自增 |
std | 方向标志 DF=1 → movsb/movsw 执行后 si/di 自减 |
movsb | 字节串传送:es:[di] = ds:[si],然后 si±1、di±1(由 DF 决定) |
loop s | cx -= 1,若 cx ≠ 0 则跳转到标签s |
int 21H | DOS 中断:ah=4cH 时程序退出,al 为返回码(此处ax=4c00H即ah=4cH, al=00H) |
rep指令
1.REP 指令的核心定义
REP(Repeat)是 x86 汇编中串操作的重复前缀指令,本身不执行数据操作,仅控制后续串指令(如 MOVS、STOS、LODS 等)的重复执行次数,直到计数寄存器(CX/ECX/RCX)的值减为 0。
关键属性:
- 前缀特性:必须紧跟在串指令前(如
REP MOVSB),不能单独执行; - 计数依赖:重复次数由 CX(16 位)、ECX(32 位)、RCX(64 位)决定,每执行一次串指令,计数寄存器自动减 1;
- 终止条件:当计数寄存器 = 0 时,立即停止重复,CPU 转而执行后续指令;
- 无标志影响:执行 REP 不会修改 FLAGS 寄存器(DF、ZF 等由串指令本身决定)。
2.REP 的执行流程(底层逻辑)
以REP MOVSB为例,CPU 执行步骤如下:
- 检查计数:判断 CX/ECX/RCX 是否为 0,若为 0 则跳过串指令,直接执行后续代码;
- 执行串指令:执行一次紧跟的串指令(如 MOVSB、STOSB 等);
- 计数递减:计数寄存器(CX/ECX/RCX)减 1(无借位,不影响 FLAGS);
- 循环判断:回到步骤 1,重复上述过程。
简化逻辑:
while (CX != 0) { 执行串指令; CX--; }
总结:rep movsb等价于s:movsb loops
rep movsw等价于s:movsw loops
;用串传送指令,将F000H段中的最后16个字符复制到data段中。
assume cs:code,ds:data
data segment
db 16 dup(0)
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0ffffH
mov ax,data
mov es,ax
mov di,15
mov cx,16
std
rep movsb
mov ax,4c00H
int 21H
code ends
end start
关键知识点总结
- 8086 寻址规则:物理地址 = 段寄存器 × 16 + 偏移量;
- 方向标志 DF:
std:DF=1,rep movsb时si/di自动减 1(逆序复制);cld:DF=0,rep movsb时si/di自动加 1(顺序复制);
- rep movsb:
- 功能:复制
ds:si指向的字节到es:di; - 循环:
cx--,直到cx=0停止;
- 功能:复制
adc-带进位加法指令
ADC(Add with Carry,带进位加法)是汇编语言中的核心算术指令,在基础加法(ADD)的基础上,额外加上标志寄存器中的进位标志(CF,Carry Flag),主要用于多字节 / 多字长数据的加法运算(比如 32 位、64 位甚至更长位数的数值相加)。
一、核心功能
指令格式:ADC 目的操作数, 源操作数
运算逻辑:目的操作数 = 目的操作数 + 源操作数 + CF
- CF(进位标志):由上一次算术运算(如 ADD、ADC、SUB 等)产生,若运算结果超出操作数位数(如 8 位加法结果 > 255),CF=1,否则 CF=0。
- 支持的操作数类型:寄存器、内存、立即数(需符合汇编器语法规则),且操作数位数需一致(8 位 / 16 位 / 32 位 / 64 位)。
sbb-带借位减法指令
sbb(Subtract with Borrow,带借位减法)是汇编语言中的算术运算指令,核心功能是将源操作数从目的操作数中减去,同时减去标志寄存器中的借位标志(CF,Carry Flag),最终结果存入目的操作数。
一、指令格式
通用格式:sbb 目的操作数, 源操作数
本质计算逻辑:目的操作数 = 目的操作数 - 源操作数 - CF
二、代码示例
mov al, 5 ; AL = 5
mov bl, 3 ; BL = 3
sub al, bl ; AL = 5-3=2,CF=0(无借位)
mov cl, 1 ; CL = 1
sbb al, cl ; AL = 2 - 1 - 0 = 1,CF=0
; 若修改初始值,制造借位:
mov al, 2
mov bl, 3
sub al, bl ; AL = 2-3 = 0xFF(补码),CF=1(有借位)
mov cl, 1
sbb al, cl ; AL = 0xFF - 1 - 1 = 0xFD,CF=1
cmp指令
CMP(Compare,比较)是汇编语言中核心的算术运算指令之一,用于比较两个操作数的大小 / 相等性,其核心逻辑是:用第一个操作数减去第二个操作数,但不保存减法结果,仅根据减法结果修改处理器的标志寄存器(FLAGS)(如零标志 ZF、符号标志 SF、进位标志 CF、溢出标志 OF 等),后续通过条件跳转指令(如 JE、JNE、JG、JL 等)根据标志位判断比较结果。
1. 基本格式
CMP 目的操作数, 源操作数 ; 等价于:目的操作数 - 源操作数(结果不保存,仅更新标志位)
2. 操作数组合(8086 支持的合法形式)
| 目的操作数 | 源操作数 | 示例 | 说明 |
|---|---|---|---|
| 寄存器 | 寄存器 | CMP AX, BX | 16 位寄存器比较 |
| 寄存器 | 内存 | CMP CL, [0010H] | 8 位寄存器 vs 内存字节 |
| 内存 | 寄存器 | CMP [SI], DX | 16 位内存 vs 16 位寄存器 |
| 寄存器 | 立即数 | CMP BX, 1000H | 16 位寄存器 vs 立即数 |
| 内存 | 立即数 | CMP [DI+2], 05H | 8 位内存 vs 8 位立即数 |
⚠️ 注意:
- 不支持「内存 vs 内存」直接比较(需先将一个内存值加载到寄存器);
- 操作数位数必须一致(8 位 / 16 位匹配,如 CMP AL, BX 非法);
- 段寄存器(CS/DS/ES/SS)不能作为 CMP 的操作数。
3.对标志寄存器的影响
CMP 执行 OP1 - OP2 后,会修改以下关键标志位(FLAGS 寄存器),这是判断比较结果的核心:
| 标志位 | 全称 | 含义 |
|---|---|---|
| ZF | Zero Flag | 零标志:结果为 0 时置 1(OP1 = OP2),否则置 0 |
| SF | Sign Flag | 符号标志:结果最高位为 1 时置 1(结果为负,即 OP1 < OP2),否则置 0 |
| OF | Overflow Flag | 溢出标志:有符号数运算溢出时置 1,否则置 0 |
| CF | Carry Flag | 进位 / 借位标志:无符号数减法产生借位时置 1(OP1 < OP2),否则置 0 |
| PF | Parity Flag | 奇偶标志:结果低 8 位中 1 的个数为偶数时置 1(一般不用于比较判断) |
4.无符号数的大小判断(仅看 ZF + CF)
无符号数无正负,仅需关注「借位(CF)」和「相等(ZF)」,规则如下:
| 大小关系 | 标志位条件 | 通俗解释 |
|---|---|---|
| OP1 == OP2 | ZF = 1 | 减法结果为 0,两数相等 |
| OP1 != OP2 | ZF = 0 | 减法结果非 0,两数不等 |
| OP1 > OP2 | CF = 0 且 ZF = 0 | 无借位(OP1≥OP2)且不相等 → OP1>OP2 |
| OP1 ≥ OP2 | CF = 0 | 无借位,无论是否相等 → OP1≥OP2 |
| OP1 < OP2 | CF = 1 | 减法需借位 → OP1<OP2 |
| OP1 ≤ OP2 | CF = 1 或 ZF = 1 | 借位(OP1<OP2)或相等 → OP1≤OP2 |
条件转移指令
1. 基于零标志(ZF)的跳转(判断 “等于 / 不等于”)
| 指令 | 条件 | 含义 | 适用场景 |
|---|---|---|---|
| JE | ZF=1 | 等于(Jump Equal) | 两数相等时跳转 |
| JZ | ZF=1 | 为零(Jump Zero) | 运算结果为 0 时跳转 |
| JNE | ZF=0 | 不等于(Jump Not Equal) | 两数不等时跳转 |
| JNZ | ZF=0 | 不为零(Jump Not Zero) | 运算结果非 0 时跳转 |
2. 基于无符号数比较的跳转(CF/ZF)
无符号数比较用CMP a, b(等价于a - b,仅更新标志位),跳转指令关注 “大小关系”:
| 指令 | 条件 | 含义 | 等价关系(CMP a,b) |
|---|---|---|---|
| JB | CF=1 | 低于(Jump Below) | a < b(无符号) |
| JNAE | CF=1 | 不高于等于(Jump Not Above or Equal) | 同上 |
| JC | CF=1 | 有进位(Jump Carry) | 同上(语义不同) |
| JNB | CF=0 | 不低于(Jump Not Below) | a ≥ b(无符号) |
| JAE | CF=0 | 高于等于(Jump Above or Equal) | 同上 |
| JNC | CF=0 | 无进位(Jump Not Carry) | 同上(语义不同) |
| JA | CF=0 且 ZF=0 | 高于(Jump Above) | a > b(无符号) |
| JNBE | CF=0 且 ZF=0 | 不低于等于(Jump Not Below or Equal) | 同上 |
| JNA | CF=1 或 ZF=1 | 不高于(Jump Not Above) | a ≤ b(无符号) |
| JBE | CF=1 或 ZF=1 | 低于等于(Jump Below or Equal) | 同上 |
3. 基于有符号数比较的跳转(SF/OF/ZF)
| 指令 | 条件 | 含义 | 等价关系(CMP a,b) |
|---|---|---|---|
| JL | SF≠OF(且 ZF=0) | 小于(Jump Less) | a < b(有符号) |
| JNGE | SF≠OF(且 ZF=0) | 不大于等于 | 同上 |
| JNL | SF=OF | 不小于 | a ≥ b(有符号) |
| JGE | SF=OF | 大于等于 | 同上 |
| JG | SF=OF 且 ZF=0 | 大于(Jump Greater) | a > b(有符号) |
| JNLE | SF=OF 且 ZF=0 | 不小于等于 | 同上 |
| JNG | SF≠OF 或 ZF=1 | 不大于 | a ≤ b(有符号) |
| JLE | SF≠OF 或 ZF=1 | 小于等于 | 同上 |
4. 其他常用条件跳转
| 指令 | 条件 | 含义 | 用途 |
|---|---|---|---|
| JC | CF=1 | 有进位 | 无符号数进位判断 |
| JNC | CF=0 | 无进位 | 同上 |
| JO | OF=1 | 有溢出 | 有符号数溢出判断 |
| JNO | OF=0 | 无溢出 | 同上 |
| JS | SF=1 | 结果为负 | 符号判断 |
| JNS | SF=0 | 结果为正 | 同上 |

浙公网安备 33010602011771号