DOS环境搭建
DOS环境搭建有几种方式,不过主要的环境都是依赖于DOSBox,有条件可以直接在xp上运行,直接就有dos环境,著需要安装MASM工具即可实现编译调试了。
方式1(win10下安装DOSBox+MASM)
安装DOSBox,之后配置MASM,将下载的MASM复制到自己的文件夹下,其中MASM.EXE文件是用来编译的,LINK.EXE是用来链接的,这两个是必须的。debug.exe是用来调试的,edit.com可以用来写汇编语言代码(推荐记事本来编写汇编语言代码)
配置完后进入DOSBox首先是挂载盘符,这里我们编辑DOSBox的配置文件(C:\Users\xxx\AppData\Local\DOSBox\dosbox-0.74-3.conf)实现启动自动挂载,自动编译2.masm文件:
mount d d:\software\DOSBox-0.74-3\MASM
d:
masm 2.asm;
link 2.obj;
之后当你编辑完汇编后,可以重启DOSBox来实现自动编译。
方式2(vscode插件一键配置)推荐
DOSBox的配置较为麻烦,这里带大家在我们熟知的VS Code里一键安装一个汇编语言的模拟、写程序以及运行调试的环境;这种方式是一键式便捷安装的方式,只需要点击安装vscode插件即可。
第一步:安装
打开VS Code中的扩展栏,并搜索MASM,找到MASM/TASM这个插件,并安装即可;
这个插件会把我们所需要的dosbox, dosbox-x, jsdos以及汇编编译器MASM都安装好,也不需要我们再去挂载之类的操作;
第二步:编写一个helloworld的汇编程序
DATA SEGMENT
PRINT DB "Hello World!", 0AH, 0DH, '$'
DATA ENDS
STACK SEGMENT STACK
DW 20 DUP(0)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK
START:
MOV AX, DATA
MOV DS, AX
MOV DX, OFFSET PRINT
MOV AH, 09
INT 21H
MOV AH, 4CH
INT 21H
CODE ENDS
END START
在VS Code右下角选择assembly(DOS)的文本格式。
第三步:编译,链接,运行/调试
在.asm文件左下角,点击dosbox MASM
,会弹出选择框,让你选择编译环境,这里提供了很多环境,这里我们选择dosbox MASM,后面会说明这几个环境有啥区别。
在选择完编译环境后,右键选择运行还是调试,随后就会打开一个dos环境编译、连接、运行或调试你的程序,当然你也可以在环境里做一些其他你想做的事。
从第一步我们知道,这个插件帮我们安装了doxbox, dosbox-x和jsdos三个环境,我们来看一下这三个环境的区别是什么:
dosbox, dosbox-x, jsdos都是和dosbox类似的dos模拟环境。
- jsdos提供类似于在网页中的效果,可自行切换尝试
- dosbox的效果,就是打开这个软件自动编译运行或调试
- dosbox-x的效果,就是DOSbox的升级版,汇编的段标识符格式也要有点区别(因为DOSbox-x用的是TASM汇编编译器),调试界面优化,类似于简易的windbg界面(看内存不是很方便)
MASM DEBUG常用命令
命令 | 功能 | 示例 |
---|---|---|
R | 查看、改变CPU寄存器的内容 | r |
D | 查看内存中的内容 | d 73a:100 |
E | 改写内存中的内容 | e 73a:100 |
U | 将内存中的机器指令翻译成汇编指令,也就是反汇编 | u 73a:100 |
T | 执行一条机器指令 (类似于VS中的逐语句) | t |
A | 以汇编指令形式在内存中写入一条机器指令 | a 出车输入指令 再回车结束输入 |
G | 类似于设置断点并执行至该断点 | g 73a:100 |
P | 单步或多步执行指令(遇到循环等会执行多步命令,类似于VS中的逐过程) | p |
DOS编译链接
DOS介绍
DOS环境是一个简单的16位操作系统平台
- 设计运行于8086和8088处理器
- 也可运行于IA-32处理器的实地址工作方式
32位Windows操作系统模拟有一个MS-DOS环境 - 基于Windows保护方式的一个8086仿真环境
DOS特点
DOS是单用户单任务操作系统
DOS系统只有一个特权级别
应用程序可以访问任意资源
- 使用IO指令直接对外设端口操作
- 修改任何主存数据
- .......
DOS编程的注意事项
16位DOS环境默认采用16位操作数尺寸
- 主要使用16位或8位寄存器、操作数和寻址方式
- 堆栈以16位为单位压入PUSH和弹出POP数据
IA-32处理器的实地址工作方式 - 还允许使用32位寄存器、操作数和寻址方式
- 可以使用大多数新增的32位通用指令
实地址存储模型
主存空间1MB( =2^20 B) : 00000H一FFFFFH
程序设计时分段管理,但有两个限制:
- 每个段最大为64KB
- 段只能开始于低4位地址全为0的物理地址处
逻辑地址和物理地址
逻辑地址=段地址∶偏移地址
- 16位段寄存器保存20位段起始地址的高16位
- 偏移地址也用16位数据表示
物理地址=段地址×16+偏移地址
16位存储器寻址方式
基址寄存器+变址寄存器+位移量
多种主存寻址方式
mov ax,wvar ;直接寻址
mov ax,[bx] ;寄存器间接寻址
mov ax,[bp+4] ;寄存器相对寻址
mov ax,[bx+si] ;基址变址寻址
mov ax,[bx+di-2] ;相对基址变址寻址
DOS应用编程
16位DOS源程序编程框架
include io16.inc ;包含16位输入输出文件
.data ;定义数据段
... ;数据定义(数据待填)
.code ;定义代码段
start: mov ax,@data ;程序执行起始位置
mov ds,ax
... ;主程序(指令待填)
exit 0 ;程序正常执行终止
... ;子程序(指令待填)
end start ;汇编结束
io16.inc
DOS应用程序的包含文件
- 提供基本声明等语句
- 用于封装源程序文件的细节内容
需要配合16位IO库文件IO16.LIB
- 共同保存于当前目录
设置数据段寄存器
DOS分段管理程序
汇编和连接程序设置了CS:IP和SS:SP
DS和ES需要用户程序设置
mov ax,@data
mov ds,ax
DOS系统调用
DOS系统调用步骤
- 在AH寄存器中设置系统功能调用号
- 在指定寄存器中设置入口参数
- 用中断调用指令(INT N)执行功能调用
- 根据出口参数分析功能调用执行情况
DOS基本功能调用(INT 21H)
子功能号 | 功能 | 参数 |
---|---|---|
AH=01H | 从标准输入设备输入一个字符 | AL=输入字符的ASCII码 |
AH=02H | 从标准输入设备输出一个字符 | DL=字符的ASCII码 |
AH=09H | 从标准输入设备输入一个字符串 | DX=字符串地址 |
AH=4cH | 程序终止 | AL=返回代码 |
退出DOS
mov ax,4c00h
int 21h
调用DOS 4CH号功能,实现执行结束退出
指令调用
DOS功能使用"INT N"指令调用
中断调用方法还应用于
- 基本输入输出系统ROM-BIOS
- Linux系统功能
mov ah,子功能号
int 21h
输入输出编程
输入指令(IN)
数据从I/0接口(外设)输入到处理器
IN ALIAX/EAX,i8/DX
例如: in al,21h
in al,dx
输出指令(OUT)
数据从处理器输出到I/0接口(外设)
OUT i8/DX,ALIAX/EAX
例如: out 21h,al
out dx,al
I/O直接寻址
I/0指令中直接提供I/0地址
- IA-32处理器只能直接提供8位I/0地址
- 只能寻址最低256个I/0地址(00~FFH)>用i8表示I/0地址
- 表达形式与立即数一样
IN ALIAX/EAX,i8/DX
OUT i8/DX,AL/AX/EAX
I/O间接寻址
I/0指令中通过寄存器间接提供I/0地址
- IA-32处理器用DX寄存器保存访问的I/0地址
- 可寻址全部I/0地址(0000~一FFFFH)
直接书写成DX,表示I/0地址 - 不需要用中括号
IN ALIAX/EAX,i8/DX
OUT i8/DX,ALIAX/EAX
CMOS RAM
CMOS RAM是使用CMOS技术的存储器芯片
- PC机用以保存配置信息以及实时时钟断点后由
- 后备电池供电,避免信息丢失>具有64个字节存储容量
- 通过两个I/O地址访问
实例
;输入一个小写字母,自动转换为大写字母
STACK SEGMENT STACK ;;定义堆栈段
DB 100 DUP (?) ;;开辟100个存储单元
STACK ENDS ; ;堆栈段结束
CODE SEGMENT ; ;定义代码段
ASSUME CS:CODE , SS:STACK
START: MOV AH ,01H ;;1号调用,从键盘输入一字符存入AL
INT 21H
SUB AL ,20H ;;将AL中字符的ASCII码减去20H变成大写字母
MOV DL ,AL ;;结果送DL
MOV AH ,02H ; ;2号调用,在屏幕上显示DL中的内容
INT 21H
MOV AH,4CH ;;返回DOS
INT 21H
CODE ENDS ;;代码段结束
END START ;;程序汇编结束