汇编语言:DOSBox 与 Debug 的使用

搭建 DOSBox & MASM 环境

在使用 Debug 之前,需要先搭建一个能运行 8086 程序的环境。由于现代操作系统无法直接运行 16 位 DOS 程序,我们使用 DOSBox 来模拟当时的运行环境。DOSBox 是一个开源的 DOS 模拟器,首先前往 DOSBox 官网下载最新的安装包。
image

按照提示完成安装后,直接启动 DOSBox。初次运行时,默认的窗口分辨率较低,且无法直接使用 MASM 工具链。
image

下载后将 MASM 工具包解压,放入 DOSBox 的安装目录或与 DOSBox 关联的文件夹中。工具包包含了:汇编器 MASM.EXE、连接器 LINK.EXE、调试器 DEBUG.EXE(以及增强版 DEBUG32.EXE)和文本编辑器 EDIT.COM,用以完成源代码编写、编译、连接、调试。
image

为了获得更好的视觉体验,修改 DOSBox 的配置文件 dosbox-0.74-3.conf。找到 [sdl] 节点,将 windowresolution 设置为 1280x1024 或更高,并将 output 设置为 opengl,以改善窗口的清晰度。
image

因为 DOSBox 是一个虚拟环境,无法直接访问宿主机的文件系统。需要通过 mount 命令将物理文件夹映射为虚拟机内的逻辑盘符,才能让 Debug、MASM 等工具在虚拟环境中被识别和调用。为了避免每次启动都要手动输入挂载命令,在配置文件的 [autoexec] 节点下添加自动执行脚本。

[autoexec]
# Lines in this section will be run at startup.
# You can put your MOUNT lines here.
mount c: C:\DOSBox-0.74-3\MASM
C:

这段配置的作用是将本地物理路径 C:\DOSBox-0.74-3\MASM 挂载为 DOSBox 虚拟环境中的 C: 盘,并在启动时自动切换至 C 盘根目录。
image

保存配置文件并重启 DOSBox,如果配置正确,启动后命令行提示符应直接显示为 C:\>
image

Debug 工具使用

R 命令

输入 debug 后,DOSBox 能成功进入 Debug 交互界面。R 命令可用于查看或改变 CPU 寄存器的内容,直接输入 r,Debug 会列出所有寄存器的当前值,并在最后一行显示 CS:IP 指向的下一条待执行指令。R 命令可以修改通用寄存器,输入 r ax,在冒号后输入新值(如 1111),即可将 AX 改为 1111H。
image

该命令也可以修改指令指针,输入 r ip 或修改 cs,可以改变程序执行的流向。例如,将 IP 改为 200H,CPU 下次就会从 CS:0200 处读取指令。
image

D 命令

D 命令用于查看内存中的原始数据,用法为 d 段地址:起始偏移地址,例如 d 1000:0。Debug 默认显示 128 字节,布局分为三部分。左边是行首地址;中间是十六进制数据,每 16 字节一行中间用 - 分隔,右边是对应的 ASCII 字符,不可显示字符用 . 代替。
image
执行一次 d 后,接着输入 d,会继续显示后续内存。
image
使用 d 段地址:起始偏移地址 结尾偏移地址,例如 d 1000:0 9 可只查看 1000:01000:9 这 10 个字节。
image
物理地址 10000H 可以表示为 1000:00FFF:100100:F000
image

E 命令

E 命令的作用是直接向内存写入数据,例如机器码、数值或字符。批量写入的方式是 e 起始地址 数据1 数据2 ...。例如 e 1000:0 0 1 2 3 4 5 6 7 8 9,将 0~9 写入内存。
image
image

输入 e 1000:10,Debug 会显示原值并等待输入。输入新值按空格跳到下一单元,直接按空格跳过,按回车结束。
image

也可以直接写入 ASCII 字符,如 e 1000:0 'a' 'b' 'c',Debug 会自动将其转换为十六进制码(61H, 62H, 63H)存入内存。
image

U 命令

U 命令用于将内存中的机器码翻译成汇编指令,用法是 u 段地址:起始偏移地址,执行后 Debug 会列出地址、机器码和对应的汇编指令。例如,我们在 1000:0 处用 E 命令写入了 B8 01 00,使用 u 1000:0 就会看到 MOV AX, 0001
image

如果内存中的数据不是有效的指令,反汇编出来的结果会是乱码,如 ADD [BX+SI], AL

T 命令

T 命令的作用是执行 CS:IP 指向的一条指令,并显示执行后所有寄存器的状态。首先使用 EA 命令向内存写入指令,如 1000:0;然后使用 R 命令修改 CS:IP,使其指向写入指令的地址,如 CS=1000, IP=0000
image

输入 t 执行,执行后 AX 等寄存器的值会改变且 IP 会增加。增加的量等于刚刚执行的指令的字节长度,从而指向下一条指令。
image

A 命令

A 命令以汇编指令的形式直接向内存中写入机器码,相比 E 命令更符合人类的思维习惯。用法是 a 段地址:偏移地址,随后逐行输入汇编指令(如 mov ax, 1),输入完一条按回车,直接按回车结束输入。输入完毕后,可以用 d 命令查看写入的机器码,或用 u 命令验证反汇编结果。
image

实验 1

逐条执行指令

使用 A 命令将程序写入内存,键入 a 1000:0 后逐行输入汇编指令。
image

写入完成后使用 U 命令查看。
image

然后使用 r csr ipCS:IP 指向 1000:0
image

反复使用 t 命令单步执行,观察寄存器的变化。执行第一条指令 mov ax, AE20H 后,AX 寄存器的值变为 AE20H,同时 IP 增加 3 字节指向下一条指令。
image

执行 add ax,1416H,AX 中的值更新为 C236H,计算过程为 AE20H + 1416H,此次运算未产生进位,CF 标志位为 0。
image

随后通过 mov bx,2000H 将 BX 赋值为 2000H
image

执行 add ax,bx,AX 变为 E236H
image

当执行 mov bx,ax 时,BX 被 AX 的值覆盖,同样变为 E236H
image

此时执行 add ax,bx,由于 AX 是 16 位寄存器只能存放 4 位十六进制数,最高位的 1 被丢弃,最终 AX 中仅保留 C46CH
image

执行 mov ax,001AHmov bx,0026H 后,AX 和 BX 分别被赋值。
image
image

执行 add al,bl 时,仅低 8 位参与运算,AL 变为 40H,而 AH 保持不变。
image

执行 add ah,blAH 变为 26H,此时 AX 整体为 2640H
image

执行 add bh,al 时,仅 BX 的高 8 位 BH 被 AL 的值修改,BX 变为 4026H
image

接着 mov ah,0 将 AH 清零,AX 变为 0040H
image

add al,bl 使 AL 变为 66H
image

最后执行 add al,9CH,这里发生了 8 位溢出。数学结果为 102H,但 AL 只能保留低 8 位,最终 AL 的值为 02H
image

计算 2 的 8 次方

使用 A 命令写入以下三条指令到 2000:0

mov ax,1
add ax,ax
jmp 2000:0003

image

设置 CS=2000IP=0000,然后使用 t 命令循环执行。
image

第一次执行 add ax,ax 后,AX=2
image

每执行一次 AX 的值翻倍,当执行到第 8 次时,AX=0100H(即十进制 256)。这是因为 jmp 2000:0003 跳回 add ax,ax 指令,形成了一个循环,2^8 = 256
image

查看 ROM 的日期

使用 d ffff:0 fd f000:ff00 查看内存,在 FFFF0H 附近可以找到 01/01/92 的日期字符串。
image

尝试用 e 命令修改该内存区域时,例如 e ffff:5 '00'。再次用 d 命令查看,内容没有任何变化。
image

这是因为 C0000H~FFFFH 这段地址空间映射的是 ROM 只读存储器,即使 CPU 发出了写命令,数据总线上的数据也不会被写入 ROM 芯片。

向 B8100H 单元填写数据

执行命令 -e B810:0000 01 01 02 02 03 03 04 04,屏幕上立刻出现了彩色的图案或字符。
image

当修改地址,图案出现的位置发生了改变。当修改写入的数据时,图案的颜色和形状也随之改变。
image
image

A0000H~BFFFFH显存地址空间,B810:0000 对应的物理地址是 B8100H,位于显存范围内。向这段地址写入数据,实际上就是向显卡的显存中写入数据,显卡会实时将显存中的比特信息输出到显示器上。

参考资料

《汇编语言(第四版)》,王爽 编著,清华大学出版社
DOSBox, an x86 emulator with DOS

posted @ 2026-08-06 13:58  乌漆WhiteMoon  阅读(6)  评论(0)    收藏  举报