汇编语言Debug工具与常用指令完全指南
本文将全面讲解Debug调试工具的使用方法,并系统介绍汇编语言中的数据传送、算术运算、逻辑处理等核心指令,通过丰富的实例帮助初学者快速掌握汇编语言编程。
一、Debug调试工具详解
Debug是DOS和Windows系统中自带的汇编语言调试工具,对于学习汇编语言和进行底层开发至关重要。
1. 汇编指令输入:A命令
A命令用于输入汇编指令,语法格式为:A [地址]
-A 1000
0B65:1000 MOV AX, 1000H
0B65:1003 MOV BX, 2000H
0B65:1006 ADD AX, BX
0B65:1008 INT 20H
2. 单步执行与寄存器查看:T命令
T命令执行一条指令并显示所有寄存器内容:
-T
AX=1000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0B65 ES=0B65 SS=0B65 CS=0B65 IP=1003 NV UP EI PL NZ NA PO NC
0B65:1003 BB0020 MOV BX,2000
3. 寄存器查看与修改:R命令
R命令用于显示和修改寄存器值:
-R ; 显示所有寄存器内容
-R AX ; 显示并修改AX寄存器
:1000 ; 输入新值或直接回车保持原值
-RF ; 显示并修改标志寄存器
标志位说明:
-
NV/OV:溢出标志(No Overflow/Overflow)
-
EI/DI:中断允许(Enable Interrupt/Disable Interrupt)
-
PL/NG:符号位(Positive/Negative)
-
NZ/ZR:零标志(Not Zero/Zero)
-
NA/AC:辅助进位(No Auxiliary Carry/Auxiliary Carry)
-
PO/PE:奇偶标志(Odd/Even)
-
NC/CY:进位标志(No Carry/Carry)
4. 内存内容查看:D命令
D命令显示指定内存区域的内容:
-D 100 110 ; 显示DS段偏移100H-110H的内容
-D 100 ; 显示DS段偏移100H-180H的内容
-D SS:100 110 ; 显示SS段偏移100H-110H的内容
-D ES:0 L10 ; 显示ES段偏移0开始的16个字节
5. 内存内容修改:E命令
E命令用于修改内存内容:
-E DS:100 3F 4F 5F ; 一次性修改多个字节
-E DS:100 ; 逐个字节修改,空格下一字节,回车结束
6. 运行与退出命令
-G=100 10E ; 执行从100H到10EH的程序
-Q ; 退出Debug程序
二、汇编语言基本指令详解
1. 数据传送类指令
(1) 数据传送MOV指令
MOV指令格式:MOV 目标操作数, 源操作数
; 立即数传送
MOV AX, 1000H ; 16位立即数送AX
MOV BL, 05H ; 8位立即数送BL; 寄存器间传送
MOV AX, BX ; BX内容送AX
MOV AH, AL ; AL内容送AH
MOV DS, AX ; 通用寄存器送段寄存器(需通过通用寄存器中转); 寄存器与存储器间传送
MOV AX, [BX] ; 存储器内容送AX
MOV [BX+SI], AX ; AX内容送存储器
MOV DX, ES:[SI] ; 附加段存储内容送DX
MOV指令限制:
-
❌ 立即数不能直接送段寄存器:
MOV DS, 100H
-
❌ 存储单元之间不能直接传送:
MOV [BX], [SI]
-
❌ 代码段寄存器CS不能作为目标操作数
-
❌ 段寄存器之间不能直接传送:
MOV DS, ES
(2) 数据交换XCHG指令
XCHG AX, BX ; 寄存器间交换
XCHG AX, [BX+SI] ; 寄存器与存储器交换
XCHG [DI], CX ; 存储器与寄存器交换
XCHG指令限制:
-
❌ 不能交换段寄存器
-
❌ 不能交换立即数
-
❌ 不能交换两个存储单元
(3) 堆栈操作指令PUSH/POP
; 示例:将FF11H和CCDDH压入堆栈,然后弹出CCDDH
MOV AX, FF11H
PUSH AX ; 压入FF11H
MOV AX, CCCDH
PUSH AX ; 压入CCDDH
POP BX ; 弹出CCDDH到BX
堆栈操作规则:
-
栈顶由SS:SP指向,PUSH时SP减小,POP时SP增加
-
操作数必须是16位寄存器或存储器操作数
-
操作不影响标志位
(4) 地址传送指令
LEA BX, [SI+2000H] ; 将有效地址SI+2000H送BX
LES DI, [BX+10H] ; 将双字指针送ES和DI
LDS SI, [BP+20H] ; 将双字指针送DS和SI
(5) 输入输出指令
; 输入指令
IN AL, 20H ; 从端口20H输入字节到AL
IN AX, DX ; 从DX指定端口输入字到AX; 输出指令
OUT 20H, AL ; 输出AL内容到端口20H
MOV DX, 800H ; 端口地址高于FFH时需用DX间接寻址
OUT DX, AX ; 输出AX内容到DX指定端口
(6) 标志位传送指令
LAHF ; 标志寄存器低8位送AH:S Z A P C
SAHF ; AH送标志寄存器低8位
PUSHF ; 标志寄存器16位全部压栈
POPF ; 栈顶内容弹出到标志寄存器
(7) 换码指令XLAT
MOV BX, OFFSET TABLE ; 表首地址送BX
MOV AL, 03H ; 索引值送AL
XLAT ; AL = DS:[BX+AL],查表转换
2. 算术运算类指令
(1) 加减法指令
; 基本加减法
ADD AX, 1000H ; AX = AX + 1000H
SUB [BX], 500H ; 存储器内容减500H
ADC AX, BX ; 带进位加:AX = AX + BX + CF
SBB CX, DX ; 带借位减:CX = CX - DX - CF; 增量和减量
INC AX ; AX = AX + 1
DEC WORD PTR [BX] ; 存储器内容减1; 比较指令
CMP AX, BX ; 比较AX和BX,设置标志位
标志位判断规则:
比较类型 | 条件 | 标志位状态 |
---|---|---|
无符号数 ≥ | AX ≥ BX | CF = 0 |
无符号数 < | AX < BX | CF = 1 |
有符号数 ≥ | AX ≥ BX | SF = OF |
有符号数 < | AX < BX | SF ≠ OF |
相等 | AX = BX | ZF = 1 |
(2) 求补指令
NEG BX ; BX = 0 - BX,求补运算(按位取反加1)
(3) 乘法指令
; 无符号乘法
MOV AL, 10H
MOV BL, 20H
MUL BL ; AX = AL × BL = 0200H; 有符号乘法
MOV AL, -2 ; AL = FEH (-2的补码)
MOV BL, 4
IMUL BL ; AX = AL × BL = FFF8H (-8的补码)
(4) 除法指令
; 无符号除法
MOV AX, 0400H ; 被除数400H
MOV BL, 80H ; 除数80H
DIV BL ; AL=08(商), AH=00(余数); 有符号除法
MOV AX, -40 ; 被除数-40
MOV BL, 3 ; 除数3
IDIV BL ; AL=-13(商), AH=-1(余数)
(5) 符号扩展指令
CBW ; AL符号位扩展到AH,将字节扩展为字
; 示例:AL=FFH(-1) → AX=FFFFH(-1)
CWD ; AX符号位扩展到DX,将字扩展为双字
; 示例:AX=8000H(-32768) → DX=FFFFH, AX=8000H
(6) BCD码调整指令
; 压缩BCD码调整
MOV AL, 28H ; 28(BCD)
ADD AL, 35H ; AL=5DH(非BCD码)
DAA ; AL=63H(调整后的BCD码,63); 非压缩BCD码调整
MOV AL, '8' ; AL=38H
ADD AL, '5' ; AL=8DH
AAA ; AL=03H, AH=01H(结果为13)
(7) 综合计算示例
计算表达式:(1234H + 345H × 12H - 2363H) / 96H
; 分步计算过程:
MOV AX, 345H
MOV BX, 12H
MUL BX ; DX:AX = 345H × 12H = 0003ADAH
MOV CX, AX ; 保存结果低16位
MOV BP, DX ; 保存结果高16位MOV AX, 1234H
ADD AX, CX ; 低16位相加
ADC DX, BP ; 高16位带进位相加SUB AX, 2363H ; 减去2363H
SBB DX, 0 ; 高16位带借位减MOV BX, 96H
DIV BX ; AX = 商, DX = 余数
3. 逻辑运算类指令
AND AX, 0FFFFH ; 按位与,可用于屏蔽某些位
OR AX, 0000H ; 按位或,可用于设置某些位
XOR AL, AL ; 按位异或,AL清零
NOT AX ; 按位取反
TEST AX, 1111H ; 测试指令,仅设置标志位
4. 移位指令
(1) 基本移位指令
SHL AX, 1 ; 逻辑左移,最低位补0,最高位进CF
SHR AX, 1 ; 逻辑右移,最高位补0,最低位进CF
SAL AX, 1 ; 算术左移,与SHL相同
SAR AX, 1 ; 算术右移,最高位符号位保持不变
(2) 循环移位指令
ROL AX, 1 ; 循环左移,最高位移到最低位同时进CF
ROR AX, 1 ; 循环右移,最低位移到最高位同时进CF
RCL AX, 1 ; 带进位循环左移,CF移到最低位,最高位移到CF
RCR AX, 1 ; 带进位循环右移,CF移到最高位,最低位移到CF
5. 程序控制指令
(1) 无条件转移
JMP 1111H ; 无条件跳转到地址1111H
JMP SHORT LABEL ; 短转移(-128到127字节)
JMP NEAR PTR LABEL ; 近转移(同一段内)
JMP FAR PTR LABEL ; 远转移(不同段间)
(2) 条件转移指令
指令 | 条件 | 描述 |
---|---|---|
JC/JB/JNAE | CF=1 | 低于/进位时转移 |
JNC/JNB/JAE | CF=0 | 高于等于/无进位时转移 |
JE/JZ | ZF=1 | 相等/为零时转移 |
JNE/JNZ | ZF=0 | 不相等/不为零时转移 |
JS | SF=1 | 为负数时转移 |
JNS | SF=0 | 为非负数时转移 |
JO | OF=1 | 溢出时转移 |
JNO | OF=0 | 无溢出时转移 |
JP/JPE | PF=1 | 偶校验时转移 |
JNP/JPO | PF=0 | 奇校验时转移 |
三、Debug实战编程示例
示例1:计算1+2+3+...+10的和
-A 100
0B65:0100 MOV AX, 0000 ; 初始化累加器
0B65:0103 MOV CX, 000A ; 设置循环次数10
0B65:0106 MOV BX, 0001 ; 起始值1
0B65:0109 ADD AX, BX ; 累加
0B65:010B INC BX ; 增量
0B65:010C LOOP 0109 ; 循环
0B65:010E INT 3 ; 断点中断-G=100 10E ; 执行程序
执行后查看AX寄存器,应显示结果0037H(55的十六进制)。
示例2:字符串复制程序
-A 200
0B65:0200 MOV SI, 0500 ; 源字符串地址
0B65:0203 MOV DI, 0600 ; 目标地址
0B65:0206 MOV CX, 000F ; 复制15个字节
0B65:0209 MOV AL, [SI] ; 取源字符
0B65:020B MOV [DI], AL ; 存目标地址
0B65:020D INC SI ; 源指针加1
0B65:020E INC DI ; 目标指针加1
0B65:020F LOOP 0209 ; 循环复制
0B65:0211 INT 20 ; 程序结束-E 500 "Hello, World!" 0D 0A ; 设置源字符串
-G=200 211 ; 执行复制程序
-D 600 L10 ; 查看复制结果
四、常见问题与调试技巧
-
地址计算错误:注意段地址和偏移地址的换算,物理地址=段地址×16+偏移地址
-
堆栈平衡问题:PUSH和POP要成对使用,避免堆栈不平衡导致程序崩溃
-
标志位误解:特别注意有符号数和无符号数判断条件的区别
-
数据类型匹配:确保操作数类型一致,如字节操作使用8位寄存器,字操作使用16位寄存器
-
调试技巧:
-
使用T命令单步执行,观察每条指令执行后的寄存器变化
-
使用D命令查看内存数据,验证数据是否正确存储
-
使用G命令设置断点,分段调试程序
-
遇到问题时,检查标志位状态,分析程序逻辑
-
学习建议:
-
多动手实践,通过Debug工具验证每条指令的功能
-
从简单小程序开始,逐步增加复杂度
-
注重理解指令对标志位的影响
-
掌握常见编程模式,如循环、条件判断、子程序调用等
-
参考Intel官方指令手册,获取最权威的指令说明
推荐视频教程如下:
使用经典DOS进行汇编语言的Debug