手把手调试指南:用Debug玩转你的第一个MASM汇编程序(附常用命令清单)
手把手调试指南:用Debug玩转你的第一个MASM汇编程序(附常用命令清单)
当你第一次看到DOSBox黑底绿字的界面时,那种既熟悉又陌生的感觉可能会让你想起老式计算机的复古魅力。但真正让人头疼的是,当你的第一个MASM汇编程序编译通过却运行异常时,面对古老的Debug工具,那种无从下手的茫然感。别担心,这篇文章就是为你准备的——我们将把Debug工具当作你的"时光显微镜",带你深入8086处理器的内部世界。
想象一下,Debug就像是一台可以暂停时间的机器,让你能够观察每条指令执行时CPU内部发生的每一个细微变化。这比现代IDE的调试器更加原始,但也更加透明和直接。下面我们就从一个预设了典型错误的示例程序开始,一步步揭开Debug的神秘面纱。
1. 调试前的准备工作:搭建你的"考古"实验室
在开始调试之前,确保你已经完成了以下准备工作:
- 已安装DOSBox 0.74-3或更高版本
- 已配置好MASM汇编环境
- 有一个可以编译通过的.asm源文件
- 生成了对应的.exe可执行文件
这里我们使用一个故意设置了错误的示例程序error.asm:
datas segment message db "Debug is fun!",0ah,0dh,'$' datas ends stacks segment dw 128 dup(?) stacks ends codes segment assume cs:codes, ds:datas, ss:stacks start: mov ax, stacks ; 错误:应该加载datas段地址 mov ds, ax mov dx, offset message mov ah, 09h int 21h mov ax, 4c00h int 21h codes ends end start这个程序故意将数据段地址加载错误,导致运行时无法正确显示字符串。我们将用Debug来找出并修复这个问题。
2. Debug基础:你的第一个调试会话
启动调试会话非常简单,在DOSBox中运行:
debug error.exe你会看到一个简洁的提示符"-",这就是Debug的交互界面。让我们先熟悉几个最基础但至关重要的命令:
2.1 查看和修改寄存器:R命令
输入r命令,你会看到类似如下的输出:
AX=0000 BX=0000 CX=0042 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=0B3F ES=0B3F SS=0B4F CS=0B4F IP=0100 NV UP EI PL NZ NA PO NC这些寄存器值中,有几个特别值得关注:
- CS:IP:指向下一条要执行的指令
- DS:数据段寄存器
- SS:SP:堆栈指针
要修改某个寄存器的值,可以使用r 寄存器名,例如:
r ax AX 0000 :1234 ; 将AX修改为1234h2.2 反汇编代码:U命令
u命令可以将机器码反汇编为汇编指令。不带参数时,它会从当前CS:IP开始反汇编:
u 0B4F:0100 8CC8 MOV AX,CS 0B4F:0102 8ED8 MOV DS,AX 0B4F:0104 BA0000 MOV DX,0000 0B4F:0107 B409 MOV AH,09 0B4F:0109 CD21 INT 21 0B4F:010B B8004C MOV AX,4C00 0B4F:010E CD21 INT 21你可以指定反汇编的起始和结束地址:
u 100 10e2.3 单步执行:T命令
t命令是调试过程中最常用的命令之一,它执行一条指令并显示所有寄存器的状态。让我们尝试执行前几条指令:
t AX=0B4F BX=0000 CX=0042 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=0B3F ES=0B3F SS=0B4F CS=0B4F IP=0102 NV UP EI PL NZ NA PO NC 0B4F:0102 8ED8 MOV DS,AX继续按t执行下一条指令,观察DS寄存器的变化。
3. 实战调试:定位并修复错误
现在让我们用Debug来找出我们示例程序中的错误。按照以下步骤操作:
- 启动调试会话:
debug error.exe - 使用
u命令查看反汇编代码,找到程序入口 - 使用
t命令单步执行,重点关注DS寄存器的变化 - 当执行到
MOV DX,0000时,使用d ds:0查看数据段内容
你会注意到,数据段中并没有我们预期的字符串。这是因为我们错误地将堆栈段地址加载到了DS寄存器。让我们修复这个问题:
- 使用
q退出当前调试会话 - 修改源代码,将
MOV AX,STACKS改为MOV AX,DATAS - 重新编译链接程序
- 再次启动调试会话验证修复
4. Debug高级技巧:内存查看与修改
4.1 查看内存:D命令
d命令可以显示内存内容。基本语法是:
d [段地址]:[偏移地址] [长度]例如,要查看数据段的前32个字节:
d ds:0 20输出会显示16进制和ASCII两种形式:
0B3F:0000 44 65 62 75 67 20 69 73-20 66 75 6E 21 0A 0D 24 Debug is fun!..$ 0B3F:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................4.2 修改内存:E命令
e命令可以修改内存内容。例如,要修改DS:0000处的字节:
e ds:0 0B3F:0000 44.41 ; 将第一个字节从44h改为41h('A')你也可以直接输入一串值:
e ds:10 41 42 43 44 ; 在DS:0010处写入'A','B','C','D'5. Debug命令速查表
下表总结了Debug中最常用的命令及其功能:
| 命令 | 语法 | 功能描述 |
|---|---|---|
| 反汇编 | U [起始地址] [结束地址] | 将机器码反汇编为汇编指令 |
| 单步执行 | T [指令数] | 执行一条或多条指令 |
| 运行 | G [=起始地址] [断点地址] | 运行程序直到断点 |
| 寄存器 | R [寄存器名] | 显示或修改寄存器 |
| 查看内存 | D [地址] [长度] | 显示内存内容 |
| 修改内存 | E 地址 [值列表] | 修改内存内容 |
| 汇编 | A [地址] | 输入汇编指令 |
| 退出 | Q | 退出Debug |
6. 调试实战:一个完整的调试过程
让我们通过一个完整的例子来巩固所学知识。假设我们有如下程序(sum.asm):
datas segment num1 dw 1234h num2 dw 5678h result dw ? datas ends codes segment assume cs:codes, ds:datas start: mov ax, datas mov ds, ax mov ax, num1 add ax, num2 mov result, ax mov ax, 4c00h int 21h codes ends end start调试步骤:
- 编译链接程序:
masm sum.asm+link sum.obj - 启动调试:
debug sum.exe - 反汇编查看代码:
u - 设置断点在加法指令后:
g 10e(假设加法指令在10e) - 查看结果:
d ds:4(result位于数据段偏移4处) - 验证结果:
r查看AX寄存器的值
通过这样的实践,你会逐渐熟悉Debug的工作方式,并能够快速定位汇编程序中的各种问题。记住,调试是一门实践性很强的技能,多动手尝试不同的命令和技巧,你会很快掌握这门"考古"艺术的精髓。
