一、条件汇编
在 8086 汇编语言中,条件汇编是由汇编器(如 MASM、TASM)提供的预处理功能,用于根据指定条件决定某段代码是否被汇编,核心目的是实现代码的条件编译、多版本适配或调试控制。以下从核心语法、常用指令、实战示例等维度详细讲解 8086 条件汇编的使用。
1、条件汇编的核心概念
条件汇编指令由汇编器在汇编阶段解析,而非 CPU 在执行阶段判断,因此不影响最终可执行文件的运行逻辑,仅控制 "哪些代码会被翻译成机器码"。
- 适用场景:调试开关、硬件版本适配(如 8086/8088 区分)、功能可选编译等。
- 核心指令:
IF/ELSE/ENDIF、IFDEF/IFNDEF、IFB/IFNB等。
2、常用条件汇编指令(MASM/TASM 兼容)
| 指令 | 功能说明 |
|---|---|
IF 表达式 |
表达式非 0 时,汇编后续代码(表达式支持常量、宏参数、算术 / 逻辑运算) |
ELSE |
与IF配对,表达式为 0 时汇编此段代码 |
ENDIF |
结束条件汇编块 |
IFDEF 符号 |
符号已定义(EQU/=/DEFINE)时,汇编后续代码 |
IFNDEF 符号 |
符号未定义时,汇编后续代码 |
IFB <参数> |
宏参数为空时,汇编后续代码(<>是 MASM 宏参数标识) |
IFNB <参数> |
宏参数非空时,汇编后续代码 |
IFE 表达式 |
表达式为 0 时,汇编后续代码(IF NOT) |
IFIDN <p1>,<p2> |
两个宏参数字符串完全相同时,汇编后续代码 |
IFIDNI <p1>,<p2> |
两个宏参数字符串忽略大小写相同时,汇编后续代码 |
3、基础示例:调试开关
通过定义DEBUG符号控制调试代码的编译,是条件汇编最常用的场景。
; 定义DEBUG符号(注释此行则关闭调试)
DEBUG EQU 1
; 数据段
DATA SEGMENT
MSG_DEBUG DB '调试模式:寄存器值=','$'
MSG_NORMAL DB '正常模式运行','$'
DATA ENDS
; 代码段
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
; 条件汇编:DEBUG=1时编译调试代码
IF DEBUG
; 调试逻辑:打印调试信息、查看AX寄存器
LEA DX, MSG_DEBUG
MOV AH, 09H
INT 21H
; 此处可添加寄存器打印、断点等调试代码
ELSE
; 正常逻辑:仅打印普通信息
LEA DX, MSG_NORMAL
MOV AH, 09H
INT 21H
ENDIF
; 程序退出
MOV AH, 4CH
INT 21H
CODE ENDS
END START
- 若保留
DEBUG EQU 1,汇编器会包含调试代码,最终程序打印调试信息; - 若注释
DEBUG EQU 1,汇编器会忽略调试代码,仅编译正常逻辑。
二、重复汇编
在 8086 汇编语言中,重复汇编(重复伪操作) 是汇编器提供的伪指令(而非 CPU 执行的机器指令),用于在汇编阶段重复生成一段代码 / 数据,核心目的是简化重复代码的编写,提升代码可读性和维护性。8086 常用的重复汇编伪指令主要有三类:REPT/ENDM、IRP/ENDM、IRPC/ENDM,均属于 MASM/TASM 等汇编器的伪操作。
1、核心概念
- 作用阶段 :仅在汇编阶段 生效,汇编器会将重复块展开为具体的指令 / 数据,最终生成的机器码中是 "展开后的完整代码",而非 "循环执行"(区别于 CPU 运行时的
LOOP指令)。 - 终止符 :所有重复汇编块均以
ENDM(End Macro)结束。 - 适用场景:批量定义数据、重复初始化寄存器、生成固定格式的指令序列等。
2、三类重复汇编伪指令详解
2.1. 简单重复:REPT/ENDM
语法:
REPT 重复次数
; 重复的代码/数据块
ENDM
功能 :将REPT和ENDM之间的内容重复指定次数。
示例 1:批量定义数据 批量生成 10 个字节的 0,替代手动写DB 0,0,...:
DATA SEGMENT
; 重复10次,生成10个0(字节)
REPT 10
DB 0
ENDM
DATA ENDS
汇编后等价于:DB 0,0,0,0,0,0,0,0,0,0。
**示例 2:初始化寄存器(累加器赋值)**生成将 AX 依次赋值为 1~5 的指令:
MOV CX, 0 ; 辅助计数(可选)
REPT 5
INC CX
MOV AX, CX
; 可添加其他操作(如存储、运算)
PUSH AX ; 把AX值压栈
ENDM
汇编后展开为:
MOV CX, 0
INC CX
MOV AX, CX
PUSH AX
INC CX
MOV AX, CX
PUSH AX
... ; 共5次
2.2. 带参数的重复:IRP/ENDM(Indirect Repeat with Parameter)
语法:
IRP 形参, <参数列表>
; 重复块(可使用形参)
ENDM
功能 :遍历<参数列表>中的每个参数,每次用参数替换形参,执行重复块;参数列表用尖括号<>包裹,参数间用逗号分隔。
示例 1:批量赋值寄存器将 AX、BX、CX、DX 分别赋值为 10、20、30、40:
IRP REG, <AX, BX, CX, DX>
IRP VAL, <10, 20, 30, 40>
MOV REG, VAL
ENDM
ENDM
汇编后展开为:
MOV AX, 10
MOV BX, 20
MOV CX, 30
MOV DX, 40
示例 2:批量压栈将 SI、DI、BP 依次压栈:
IRP REG, <SI, DI, BP>
PUSH REG
ENDM
汇编后等价于:PUSH SI ; PUSH DI ; PUSH BP。
2.3. 字符重复:IRPC/ENDM(Indirect Repeat with Character)
语法:
IRPC 形参, 字符串/字符列表
; 重复块(可使用形参)
ENDM
功能:遍历字符串中的每个字符,每次用字符替换形参,执行重复块;无尖括号,直接写字符串。
示例 1:生成字符常量批量定义字符 'A'、'B'、'C'、'D':
DATA SEGMENT
IRPC C, ABCD
DB 'C' ; 每次替换为当前字符
ENDM
DATA ENDS
汇编后等价于:DB 'A', 'B', 'C', 'D'。
**示例 2:寄存器操作(字符作为寄存器名)**对 AX、BX、CX 执行 XOR 清零:
IRPC R, ABC
XOR R X, 0 ; R X → AX/BX/CX
ENDM
汇编后展开为:
XOR AX, 0
XOR BX, 0
XOR CX, 0
3、关键注意事项
- 与运行时循环的区别 :
- 重复汇编:汇编阶段展开,最终代码是 "多份重复指令",无运行时开销;
LOOP指令:运行时循环,代码仅一份,通过修改寄存器重复执行。
- 参数格式 :
IRP用<参数1,参数2>,参数可为寄存器、数值、符号;IRPC直接写字符串,每个字符为一个参数。
- 嵌套使用 :重复汇编块可嵌套(如示例 1 中的
IRP嵌套),但需注意层级和ENDM匹配。 - 符号与表达式 :重复次数 / 参数可使用汇编器表达式(如
REPT 5+3等价于REPT 8)。