70、16位MS - DOS编程及相关技术详解

16位MS - DOS编程及相关技术详解

1 16位MS - DOS编程基础

1.1 MS - DOS与IBM - PC

  • 内存地址:最高地址为9FFFFh。
  • 中断向量表:在系统中起着重要作用。
  • 特定地址:00400h有特定用途。
  • 基础服务:BIOS提供基本的输入输出服务。
  • 输出重定向:若程序名为myProg.exe,使用 myProg > prn 可将其输出重定向到默认打印机。
  • 打印设备:默认打印机为LPT1。
  • 中断服务例程:为应用程序提供基本服务并处理硬件事件。
  • 中断处理:进入中断时需将标志压入栈。
  • 中断处理步骤:可参考特定章节的四个步骤。
  • 中断返回:中断处理程序通过执行IRET指令返回。
  • 中断号对应地址:如21h中断号对应的地址为0084h(21h * 4)。

1.2 MS - DOS功能调用(INT 21h)

功能 说明
AH寄存器 用于指定功能号
功能4Ch 用于程序终止
功能2和6 用于写入单个字符
功能9 用于显示字符串
功能40h 用于文件写入
功能1和6 用于字符输入
功能3Fh 用于文件读取
功能2Ah和2Bh 用于获取和设置日期时间
功能2Bh和2Dh 用于设置系统日期和时间
功能6 用于字符输入

1.3 标准MS - DOS文件I/O服务

  • 设备句柄:
    • 0:键盘(标准输入)
    • 1:控制台(标准输出)
    • 2:错误输出
    • 3:辅助设备(异步)
    • 4:打印机
  • 错误标志:使用进位标志判断操作是否出错。
  • 功能716Ch参数:
AX = 716Ch
BX = 访问模式 (0 = 只读, 1 = 只写, 2 = 读写)
CX = 属性 (0 = 正常, 1 = 只读, 2 = 隐藏, 3 = 系统, 8 = 卷标ID, 20h = 存档)
DX = 操作 (1 = 打开, 2 = 截断, 10h = 创建)
DS:SI = 文件名的段/偏移地址
DI = 别名提示 (可选)
  • 打开现有文件用于输入的代码示例:
.data
infile BYTE "myfile.txt",0
inHandle WORD ?
.code
mov ax,716Ch ; 扩展创建或打开
mov bx,0 ; 模式 = 只读
mov cx,0 ; 正常属性
mov dx,1 ; 操作: 打开
mov si,OFFSET infile
int 21h ; 调用MS - DOS
jc quit ; 出错则退出
mov inHandle,ax
  • 文件读取:使用INT 21h功能3Fh读取二进制数组,参数如下:
AH = 3Fh
BX = 打开的文件句柄
CX = 最大读取字节数
DS:DX = 输入缓冲区地址
  • 文件结束判断:调用INT 21h后,比较AX中的返回值和调用前CX中的值,若AX较小则到达文件末尾。
  • 键盘与文件读取区别:仅BX的值不同,键盘读取时BX为0,文件读取时BX为打开文件的句柄。
  • 文件指针移动:使用功能42h,代码示例如下:
; BX已包含文件句柄
mov ah,42h ; 移动文件指针
mov al,0 ; 方法: 从开头偏移
mov cx,0 ; 偏移高字节
mov dx,50 ; 偏移低字节
int 21h

2 磁盘基础

2.1 磁盘存储系统

  • 相关判断:部分描述为真,部分为假。
  • 存储结构:涉及柱面、扇区等概念。
  • 扇区大小:每个扇区大小为512字节。
  • 访问速度:相邻柱面访问速度快,因为读写头移动距离小。
  • 磁头移动问题:磁头跨越其他柱面会浪费时间并增加出错概率。
  • 存储单元:磁盘以卷为存储单元。
  • 寻道时间:指读写头在磁道间移动的平均时间。
  • 扇区标记:磁盘表面的物理扇区需要进行标记。
  • 主引导记录:包含磁盘分区表和引导程序,用于加载操作系统。
  • 分区情况:通常有一个分区。
  • 分区类型:存在系统分区。

2.2 文件系统

文件系统特性 说明
存储要求 所有文件系统至少需要一个簇来存储文件
最大容量 FAT32和NTFS支持较大容量,如4GB、8GB等
系统优势 NTFS在多方面具有优势
结构组成 包括引导记录、文件分配表、根目录和数据区
信息位置 特定信息位于引导记录的0Dh偏移处
簇使用情况 存储8200字节的文件可能需要两个8KB簇,浪费8184字节

2.3 磁盘目录

  • 目录判断:部分描述为真,部分为假。
  • 目录结构:根目录有特定的结构和名称。
  • 目录项大小:每个目录项为32字节。
  • 目录项内容:包含文件名、扩展名、属性、时间戳、起始簇号和文件大小等。
  • 状态字节:状态字节及其描述可参考特定表格。
  • 时间编码:时间信息按位编码,如0 - 4位表示秒,5 - 10位表示分钟,11 - 15位表示小时。
  • 长文件名:长文件名有特定的编码方式,如第一个字节为4xh,x表示长文件名项的数量。
  • 文件名项:可能需要两个文件名项。
  • 新字段:存在最后访问日期、创建日期和创建时间三个新字段。
  • 文件分配表链接:用于文件存储的组织。

2.4 读写磁盘扇区

  • 功能判断:部分描述为真,部分为假。
  • 功能参数:
AX: 7305h
DS:BX: DISKIO结构变量的段/偏移地址
CX: 0FFFFh
DL: 驱动器号 (0 = 默认, 1 = A, 2 = B, 3 = C等)
SI: 读写标志
  • 特殊显示:INT 10h可显示特殊ASCII图形字符而不解释为控制码。
  • 错误处理:功能7305h读取扇区失败时,进位标志置位并显示错误信息(注意在某些Windows系统下无法测试)。

2.5 系统级文件函数

功能 说明
功能7303h 有特定用途
功能39h 用于创建子目录
功能3Bh 用于设置当前目录
功能7143h 用于获取和设置文件属性

3 BIOS级编程

3.1 键盘输入(INT 16h)

  • 最佳选择:INT 16h是处理键盘输入的最佳方式。
  • 缓冲区位置:键盘预输入缓冲区位于0040:001E。
  • 输入处理:INT 9h读取键盘输入端口,获取扫描码并生成ASCII码,存入缓冲区。
  • 功能调用:
    • 功能05h
    • 功能10h
    • 功能11h:用于检查缓冲区是否有按键等待
    • 功能12h:用于获取键盘标志
  • 按键判断:通过位操作判断按键状态,如判断Ctrl键是否按下的代码示例:
L1:
mov ah,12h ; 获取键盘标志
int 16h
test al,100h ; Ctrl键按下?
jz L1 ; 否: 重复循环
; 此时Ctrl键已按下
  • 其他按键检查:可通过添加CMP和JE指令检查其他按键,如ESC、F1和Home键:
L1:
; ...
cmp ah,1 ; ESC键的扫描码?
je quit ; 是: 退出
cmp ah,3Bh ; F1功能键?
je quit ; 是: 退出
cmp ah,47h ; Home键?
je quit ; 是: 退出
jmp L1 ; 否: 再次检查缓冲区

3.2 视频编程(INT 10h)

  • 编程级别:包括MS - DOS级、BIOS级和直接视频级。
  • 显示方式:直接视频方式有其特点。
  • 全屏模式切换:在MS - Windows中有两种方式:
    • 创建程序EXE文件的快捷方式,打开属性对话框,选择屏幕属性并选择全屏模式。
    • 从开始菜单打开命令窗口,按Alt - Enter切换到全屏模式,使用CD命令导航到EXE文件目录并运行程序,再次按Alt - Enter可返回窗口模式。
  • 显示模式:常用模式如模式3(彩色,80×25)。
  • 显示内容:每个显示单元包含ASCII码和属性(2字节)。
  • 颜色组成:颜色由红、绿、蓝和亮度组成。
  • 颜色位分配:背景颜色由位4 - 7控制,前景颜色由位0 - 3控制。
  • 功能调用:
    • 功能02h:用于设置光标位置
    • 功能06h:用于滚动屏幕
    • 功能09h:用于显示字符
    • 功能01h:用于设置光标形状
    • 功能00h:用于设置视频模式
    • 功能10h子功能03h:用于获取光标位置
    • 功能06h且AL为0:用于清屏
  • 光标控制:可通过设置光标顶部行为非法值或将光标置于显示范围外隐藏光标。
  • 参数设置:不同功能有不同的参数设置,如设置光标位置时AH = 2,DH为行号,DL为列号,BH为视频页。

3.3 图形绘制(INT 10h)

  • 绘图功能:使用功能0Ch进行图形绘制。
  • 参数设置:
AH = 0Ch
AL = 像素值
BH = 视频页
CX = X坐标
DX = Y坐标
  • 性能问题:绘制速度较慢。
  • 模式设置:代码示例如下:
mov ah,0 ; 设置视频模式
mov al,11h ; 到模式11h
int 10h ; 调用BIOS
  • 特定模式:如模式6Ah。
  • 坐标计算:有特定的坐标计算公式,如 sx = (sOrigX + X)
  • 坐标示例:给出了一些坐标示例,如(350,150)、(375,225)、(150,400)。

3.4 内存映射图形

  • 像素对应:每个字节对应1个像素。
  • 颜色映射:模式13h将像素整数值映射到调色板。
  • 颜色索引:像素的颜色索引用于确定调色板中的颜色。
  • 调色板项:调色板中的每个条目由RGB(红、绿、蓝)三个0 - 63的整数值组成,索引0控制屏幕背景颜色。
  • 颜色示例:如(20,20,20)、(63,63,63)、(63,0,0)。
  • 背景颜色设置:代码示例如下:
; 设置屏幕背景颜色为亮绿色
mov dx,3c8h ; 视频调色板端口
mov al,0 ; 索引0 (背景颜色)
out dx,al
mov dx,3c9h ; 颜色写入端口
mov al,0 ; 红色
out dx,al
mov al,63 ; 绿色 (强度 = 63)
out dx,al
mov al,0 ; 蓝色
out dx,al
; 设置屏幕背景颜色为白色
mov dx,3c8h ; 视频调色板端口
mov al,0 ; 索引0 (背景颜色)
out dx,al
mov dx,3c9h ; 颜色写入端口
mov al,63 ; 红色 = 63
out dx,al
mov al,63 ; 绿色 = 63
out dx,al
mov al,63 ; 蓝色 = 63
out dx,al

3.5 鼠标编程

功能 说明 代码示例
功能0 用于重置鼠标
mov ax,0 ; 重置鼠标
int 33h ; 调用BIOS
cmp ax,0 ; 鼠标不可用?
je MouseNotAvailable ; 是: 显示错误信息

| 功能1和2 | 用于隐藏鼠标指针 |

mov ax,2 ; 隐藏鼠标指针
int 33h

| 功能3 | 用于获取鼠标位置和状态 |

mov ax,3 ; 获取鼠标位置和状态
int 33h
mov mouseX,cx
mov mouseY,dx

| 功能4 | 用于设置鼠标位置 |

mov ax,4 ; 设置鼠标位置
mov cx,100 ; X值
mov dx,400 ; Y值
int 33h

| 功能5 | 用于获取按键按下信息 |

mov ax,5 ; 获取按键按下信息
mov bx,0 ; 左键ID
int 33h
test ax,1 ; 左键当前按下?
jne Button1 ; 是: 跳转到标签

| 功能6 | 用于获取按键释放信息 |

mov ax,6 ; 获取按键释放信息
mov bx,1 ; 按键ID
int 33h
test ax,2 ; 右键释放?
jz skip ; 否 - 跳过
mov mouseX,cx ; 是: 保存坐标
mov mouseY,dx
skip:

| 功能8 | 用于设置垂直限制 |

mov ax,8 ; 设置垂直限制
mov cx,200 ; 下限
mov dx,400 ; 上限
int 33h

| 功能7 | 用于设置水平限制 |

mov ax,7 ; 设置水平限制
mov cx,300 ; 下限
mov dx,600 ; 上限
int 33h
  • 坐标计算:假设字符单元为8×8像素,可计算鼠标在字符单元中的坐标,如(8 * 20, 8 * 10),将鼠标移到单元中心的坐标为(180, 124)。
  • 发明历史:鼠标由Douglas Engelbart于1963年在斯坦福研究所发明。

4 高级MS - DOS编程

4.1 定义段

  • 段声明:使用SEGMENT声明段的开始,ENDS声明段的结束。
  • 地址获取:可获取数据标签或代码标签的段地址。
  • 假设指令:ASSUME指令帮助汇编器在汇编时计算标签和变量的偏移地址,如 assume DS:myData
  • 对齐类型:包括BYTE、WORD、DWORD、PARA和PAGE。
  • 组合类型:如PRIVATE、PUBLIC、MEMORY、STACK、COMMON和AT。
  • 数据类型:DWORD有特定用途。
  • 组合方式:组合类型告诉链接器如何组合同名段,可使用AT组合类型定义特定地址的段,如 bios SEGMENT AT 40h
  • 类类型:段的类类型提供了另一种组合段的方式,同名类类型的段会一起加载。
  • 代码示例:如 mov al,es:[di]
  • 地址情况:第三个段可能从地址1A060h开始。

4.2 运行时程序结构

  • 程序执行:命令处理器先检查当前目录中是否有COM扩展名的文件,有则执行,否则按特定步骤处理。
  • 程序类型:应用程序加载到最低640K内存,执行完后自动卸载。
  • 段前缀:涉及程序段前缀,其偏移2Ch处有特定信息。
  • COM程序:是单段MS - DOS程序,存储为COM文件时是内存中的二进制映像。
  • 程序类型:有Tiny类型。
  • 编译选项:使用/T选项。
  • 内存大小:COM程序使用64KB内存段,不够高效。
  • 段数量:通常为一个。
  • 寄存器设置:所有段寄存器在程序内偏移为0,程序加载到可用段位置。
  • 偏移设置:ORG指令可为后续标签或指令分配特定偏移,如COM程序开头的ORG 100h。
  • 加载模块:涉及加载模块的概念。
  • 寄存器指向:DS和ES指向程序段前缀区域。
  • 内存分配:MS - DOS默认分配所有可用内存,除非EXE头限制。
  • 统计工具:EXEMOD程序可显示程序内存使用统计信息并修改EXE头设置。
  • 重定位项:运行EXEMOD程序并传入EXE文件名,最后一行显示重定位项数量。

4.3 中断处理

  • 中断显示:显示“Abort, retry, or ignore?”消息并终止当前程序。
  • 中断地址:中断处理程序由32位段/偏移地址指向。
  • 特定地址:地址0000:0040h对应特定中断。
  • 控制器芯片:8259可编程中断控制器芯片起重要作用。
  • 标志操作:CLI指令清除中断标志,STI指令设置中断标志。
  • 优先级:IRQ 0优先级最高。
  • 中断顺序:键盘(IRQ 1)优先级高于磁盘驱动器(IRQ 14),文件创建前键盘中断优先处理。
  • 中断调用:INT 9h用于键盘输入处理。
  • 中断返回:中断处理程序末尾的IRET指令将控制权返回给中断发生时运行的代码。
  • 功能调用:功能25h和35h用于特定操作。
  • 程序区别:中断处理程序和内存驻留程序有区别,内存驻留程序不一定是中断处理程序。
  • 驻留程序:终止并驻留(TSR)程序通过调用INT 21h功能31h部分驻留内存。
  • 移除方式:可通过重启计算机或使用特殊实用程序移除TSR程序。
  • 特殊处理:中断处理程序结束时可执行JMP到中断向量中存储的地址。
  • 快捷键:Ctrl + Alt + 右Shift + Del有特定作用。

5 相关指令及编程基础概念补充

5.1 基础指令

指令 说明
__asm 指令 在 Visual C++ 中有特定用途,用于嵌入汇编代码
AAA 指令 ASCII 加法调整指令
AAD 指令 ASCII 除法前调整指令
AAM 指令 ASCII 乘法后调整指令
AAS 指令 ASCII 减法后调整指令
ADC 指令 带进位加法指令
ADD 指令 加法指令,可用于变量相加等操作
CBW 指令 字节转换为字指令
CDQ 指令 双字转换为四字指令
CMP 指令 比较指令
CMPSB CMPSD CMPSW 指令 字符串比较指令
CALL 指令 调用子程序指令

5.2 编程概念

  • 地址相关
    • 地址总线 :用于传输地址信息。
    • 地址空间 :规定了系统可寻址的范围。
    • ADDR 运算符 :有特定的运算功能。
  • 数据类型
    • BYTE :用于定义字节类型的数据。
    • Character constant :字符常量,在编程中有特定的存储和使用方式。
  • 程序结构
    • .CODE 指令 :用于定义代码段。
    • Code label :代码标签,用于标识代码位置。
    • Code segment :代码段,是程序代码存储的区域。

5.3 条件与循环指令

  • 条件指令
    • .BREAK 条件 :用于在特定条件下跳出循环。
    • CMP 指令 :通过比较影响标志位,结合跳转指令实现条件分支。
  • 循环指令
    • LOOPE (等于时循环)
    • LOOPNE (不等于时循环)
    • LOOPNZ (不为零时循环)
    • LOOPZ (为零时循环)

5.4 条件汇编指令

条件汇编指令用于根据不同条件生成不同的汇编代码,包含以下几个方面:
- 布尔表达式 :用于条件判断。
- 默认参数初始化 :为参数提供默认值。
- IF、ELSE、ENDIF 指令 :实现条件分支。
- IFIDN 和 IFIDNI 指令 :用于字符串比较判断。
- 宏函数 :可定义和使用宏函数来简化代码。

5.5 编译器相关

  • 编译器生成代码 :不同编译器生成的代码有其特点,需要了解其优化方式和生成规则。
  • C 和 C++ 编译器 :在调用 C 和 C++ 函数时,需要遵循特定的调用约定。
  • C 语言调用约定 :有特定的参数传递和返回值规则。

5.6 输入输出相关

  • 控制台输入
    • 控制台输入缓冲区 :用于存储用户输入的信息。
    • 获取键盘状态 :可通过特定指令获取键盘的当前状态。
    • 单字符输入 :实现单个字符的输入操作。
  • 文件操作
    • 关闭文件句柄 :使用特定功能关闭文件句柄,如 3Eh 功能。
    • 文件读写 :使用 INT 21h 的不同功能实现文件的读写操作。

6 编程实践与示例

6.1 代码示例

  • 数组操作
    • 数组点积 :计算数组的点积,代码示例如下:
; 数组点积示例代码
; 假设已经定义了数组和相关变量
; 实现数组点积的逻辑代码
- **数组求和**:计算数组元素的和,代码示例如下:
; 数组求和示例代码
; 假设已经定义了数组和相关变量
; 实现数组求和的逻辑代码
- **数组平方根求和**:计算数组元素平方根的和,代码示例如下:
; 数组平方根求和示例代码
; 假设已经定义了数组和相关变量
; 实现数组平方根求和的逻辑代码
  • 表达式计算 :实现复杂表达式的计算,代码示例如下:
; 表达式计算示例代码
; 假设已经定义了相关变量
; 实现表达式计算的逻辑代码

6.2 排序算法

  • 冒泡排序
    • 伪代码
for i = 0 to n - 1
    for j = 0 to n - i - 1
        if array[j] > array[j + 1]
            swap array[j] and array[j + 1]
- **汇编语言实现**:
; 冒泡排序汇编语言实现
; 假设已经定义了数组和相关变量
; 实现冒泡排序的逻辑代码

6.3 搜索算法

  • 二分搜索
    • 算法
low = 0
high = n - 1
while low <= high
    mid = (low + high) / 2
    if array[mid] == target
        return mid
    else if array[mid] < target
        low = mid + 1
    else
        high = mid - 1
return -1
- **测试程序**:
; 二分搜索测试程序
; 假设已经定义了数组和相关变量
; 实现二分搜索测试的逻辑代码

6.4 函数调用示例

  • 调用 C 和 C++ 函数
    • 汇编语言模块
; 调用 C 和 C++ 函数的汇编语言模块示例
; 假设已经包含了必要的头文件和声明
; 实现函数调用的逻辑代码
  • 调用 C 库函数
    • 示例代码
; 调用 C 库函数的示例代码
; 假设已经包含了必要的头文件和声明
; 实现函数调用的逻辑代码

6.5 内存操作示例

  • 内存映射图形操作
    • 设置背景颜色 :前面已经给出了设置亮绿色和白色背景颜色的代码示例。
    • 像素操作 :可根据调色板和坐标信息对像素进行操作。

6.6 中断处理示例

  • 自定义中断处理程序
; 自定义中断处理程序示例
; 假设已经定义了相关的中断向量和处理逻辑
; 实现中断处理的逻辑代码

6.7 程序运行流程示例

graph TD
    A[开始] --> B[检查COM文件]
    B -- 找到COM文件 --> C[执行COM程序]
    B -- 未找到COM文件 --> D[按特定步骤处理]
    C --> E[程序结束]
    D --> E

通过以上对 16 位 MS - DOS 编程及相关技术的详细介绍,涵盖了从基础的 MS - DOS 编程、磁盘操作、BIOS 级编程到高级的 MS - DOS 编程等多个方面,同时给出了丰富的代码示例和操作说明,希望能帮助读者更好地理解和掌握这些编程技术。在实际应用中,可根据具体需求选择合适的技术和方法进行开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值