第一个程序:环境搭建与 Hello World
学习汇编需要实际动手写代码、运行、调试。这一篇讲如何搭建环境、编译、运行汇编程序。
环境选择
8086 汇编是 16 位实模式程序,现代 Windows/Linux/macOS 不能直接运行,需要通过 DOS 模拟器。
推荐方案:DOSBox + MASM(经典组合,王爽教材使用的就是这个环境)。
方式一:VS Code 插件(推荐,最方便)
- 在 VS Code 中安装 MASM/TASM 插件
- 新建一个文件夹作为项目目录,用 VS Code 打开
- 按
Ctrl+Shift+P,搜索 “Open Settings (JSON)“,打开项目的settings.json - 粘贴以下配置:
{
"masmtasm.ASM.emulator": "msdos player",
"masmtasm.dosbox.run": "exit",
"masmtasm.ASM.assembler": "MASM-v5.00",
"masmtasm.ASM.actions": {
"MASM-v5.00": {
"baseBundle": "/MASM-v5.00.jsdos",
"before": [
"set PATH=C:\\MASM"
],
"run": [
"masm ${file};",
"link ${filename};",
">${filename}"
],
"debug": [
"masm ${file};",
"link ${filename}.OBJ;",
">debug ${filename}.exe"
],
"support": ["jsdos", "dosbox", "dosboxX", "msdos player"]
}
}
}
- 新建
.asm文件,右键选择 “Run ASM” 运行,或 “Debug ASM” 调试
方式二:DOSBox + MASM(手动配置)
- 下载安装 DOSBox 和 MASM 编译工具包
- 创建工作目录,如
D:\DOS\MASM\test - 将 MASM 的编译工具(masm.exe、link.exe、debug.exe 等)放到该目录
- 运行 DOSBox,输入以下命令挂载目录:
mount c D:\DOS\MASM
c:
path c:\
- 为了避免每次启动都输入,可以配置 DOSBox 的自动执行:
- 找到
DOSBox 0.74-3 Options.bat,双击打开配置文件 - 拉到最底部的
[autoexec]部分,添加上述 mount 和 path 命令 - 保存后每次启动 DOSBox 就自动挂载好了
- 找到
常见问题
路径问题
- 路径中不要包含中文或空格,否则 DOSBox 可能找不到文件
- 如果 VS Code 提示找不到 DOSBox,在插件设置中手动指定 dosbox.exe 的路径
- 修改设置后必须重启 VS Code 才生效
最小可运行程序
assume cs:code
code segment
start:
; 这里写你的代码
mov ax, 4c00H ; 程序退出,AH=4CH 是DOS退出功能号
int 21H ; 调用 DOS 系统中断
code ends
end start
编译运行流程
源文件(.asm) → masm编译 → 目标文件(.obj) → link链接 → 可执行文件(.exe) → 运行/调试
在 DOSBox 中手动编译运行:
masm test.asm; ; 编译(; 表示跳过中间提问,用默认值)
link test.obj; ; 链接
test.exe ; 运行
debug test.exe ; 用 debug 调试
debug 调试命令
debug 是 DOS 自带的调试工具,学习汇编一定要会用:
| 命令 | 功能 | 示例 |
|---|---|---|
r | 查看/修改寄存器值 | r 查看所有,r ax 修改 AX |
d | 查看内存内容(Dump) | d 1000:0 查看段地址1000偏移0处的内存 |
e | 修改内存内容(Edit) | e 1000:0 01 02 03 写入数据 |
u | 反汇编(Unassemble) | u 将内存内容翻译成汇编指令 |
t | 单步执行(Trace) | t 执行一条指令,进入中断内部 |
p | 单步执行(不进入中断) | p 遇到 int 21H 时用这个,不会进入中断 |
g | 连续执行(Go) | g 执行到程序结束,g 0012 执行到偏移0012处 |
a | 写入汇编指令(Assemble) | a 1000:0 直接在内存中输入汇编指令 |
q | 退出 debug | q |
t 和 p 的区别
t(Trace):单步进入,遇到int 21H或call会进入子程序内部p(Proceed):单步跳过,遇到中断或子程序会一次执行完,不会进去 一般调试时大部分用t,遇到int 21H这种系统中断用p。
程序退出
每个程序都必须正确退出返回 DOS,否则 CPU 会继续执行后面的内存内容导致崩溃:
mov ax, 4c00H ; AH = 4CH(DOS退出功能号),AL = 00H(返回码,0表示正常)
int 21H ; 调用 21H 号 DOS 中断
不要忘记退出!
如果没有这两行,CPU 执行完你的代码后会继续往下跑,把后面内存中的数据当成指令执行,大概率死机或崩溃。
写一个能看到效果的程序
直接操作显存显示字符(详见 显存部分):
assume cs:code
code segment
start:
mov ax, 0B800H
mov es, ax ; ES 指向显存段地址 B800H
mov bx, 0 ; 偏移地址从0开始(屏幕左上角)
; 在屏幕中央显示一个字符 'A',白底黑字
mov byte ptr es:[bx], 'A' ; 字符
mov byte ptr es:[bx+1], 70H ; 属性:白底(7)黑字(0),0表示不闪烁
mov ax, 4c00H
int 21H
code ends
end start
debug 查看显存的注意事项
在 DOSBox 中用
d B800:0看显存时,数据会不停变化——因为 DOSBox 本身也在用显存显示你输入的内容,这不是你的程序有问题。