(一)程序说明:本程序必须在纯 DOS 环境运行,因为 int 13h 中断例程只能在纯 DOS 环境运行。
(二)安装程序的代码
1. 参数说明:
(1) 用 AH 寄存器传递功能号:0 表示读,1 表示写。
由于要调用 BIOS 的 int 13h 中断例程,而 int 13h 中断例程的 AH 寄存器参数为:(ah)=2 或 (ah)=3。所以需要执行“add ah,2”指令,以转换 AH 寄存器存储的数据来适应 int 13h 中断例程的调用:
add ah,2 ; (ah)=0 或 (ah)=1,调用 BIOS 的 int 13h 中断时,(ah)=2 或 (ah)=3
(2) 用 DX 寄存器传递要读写的扇区的逻辑扇区号。
转换物理扇区的面号、磁道号、扇区号用到的除法运算方法,参见《课程设计 1》 的 divdw 子程序代码。
(3) 用 es:bx 指向存储读出数据或写入数据的内存区。
2. int 7Ch 中断例程说明:
(1) 读功能:将指定软盘位置所存储的字符串数据读入指定的内存区域。
(2) 写功能:将指定内存区域中的字符串数据写入软盘的某个存储位置。
注意,所需要显示的字符串数据由测试 int 7Ch 中断的程序提供。
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset rwd
mov ax,0
mov es,ax
mov di,200h
mov cx,offset rwdend-offset rwd
cld
rep movsb
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov ax,4c00h
int 21h
; int 7Ch 中断例程
; begin int 7Ch
; 参数说明:
; (al)=1
; 由于字符串数据占用的存储空间不会超过 512 字节(即 512 个字符),所以只需 1 个扇区来存储。
; (al) 参数由测试程序提供,因为需要读取或写入的字符串数据也是由测试程序提供,所以在测试程序中才可以确定需要读取或写入字符串数据的大小。
; (ah)=0 读 (ah)=1 写
; 需用“add ah,2”指令转换为 int 13h 中断例程的参数:(ah)=2 读 (ah)=3 写
; (dx)=逻辑扇区号
; 转换成 int 13h 中断例程的参数:(dh)=面号 (dl)=驱动器号 (ch)=磁道号 (cl)=扇区号
; 转换方法:通过调用 divdw 除法运算子程序(参见《课程设计 1》)来实现转换
; es:bx 指向存储着读取字符串数据或写入字符串数据的内存区域
rwd: push bx
push ax
mov cx,1440 ; 除数
mov ax,dx ; 逻辑扇区号值的低 16 位
mov dx,0 ; 逻辑扇区号值的高 16 位
call divdw ; 调用 divdw 子程序,执行“逻辑扇区号 ÷ 1440”运算
mov bx,ax ; 将“逻辑扇区号 ÷ 1440”所得的磁盘面号(商)转存入 BX 寄存器
mov ax,cx ; 将“逻辑扇区号 ÷ 1440”所得余数转存入 AX 寄存器,以备后面使用
mov cx,18 ; 除数
call divdw ; 调用 divdw 子程序,执行“rem(逻辑扇区号 ÷ 1440)÷18”运算
mov ch,al ; 将磁道号存入 CH 寄存器
inc cl ; CL 寄存器存储扇区号
mov dh,bl ; 将面号存入 DH 寄存器
mov dl,0 ; DL 寄存器存储驱动器号
pop ax
pop bx
add ah,2 ; 将 (ah) 参数转换成 int 13h 中断例程的功能号
int 13h ; 调用 int 13h 中断例程
rwdrep: iret
; divdw 子程序的代码取自《课程设计 1》
; begin divdw
; 执行 divdw 子程序前已预先设置参数:
; (ax) = 被除数的低 16 位 (dx) = 被除数的高 16 位 (cx) = 除数
; 执行 divdw 子程序后返回的情况(指执行返回前的系列 pop 指令和 ret 指令之前):
; (ax) = 商数的低 16 位 (dx) = 商数的高 16 位 (cx) = 余数
divdw: push bx
; 执行高 16 位被除数与原 16 位除数之间的除法运算
mov bx,ax ; 将被除数的低 16 位暂存到 BX 寄存器
mov ax,dx ; 将被除数的高 16 位转存到 AX 寄存器
mov dx,0 ; 设置原被除数高 16 位进行的除法运算所需要使用的高 16 位被除数
div cx ; 执行高 16 位除法运算,计算结果的余数默认存储于 DX 寄存器
mov bp,ax ; 将高 16 位除法运算所得的商数转存到 BP 寄存器
mov ax,bx ; 将被除数的低 16 位传送回 AX 寄存器
div cx ; 执行低 16 位除法运算,计算结果的商数默认存储于 AX 寄存器
mov cx,dx ; 将低 16 位除法运算所得的余数(也是最终除法运算的余数)转存到 CX 寄存器
mov dx,bp ; 将高 16 位除法运算所得的商数转存到 DX 寄存器
; 经 divdw 子程序上述操作后,AX、DX 和 CX 寄存器分别存储着商数的低 16 位、高 16 位和余数
pop bx
ret
; end divdw
rwdend: nop
; end int 7Ch
code ends
end start
(三)测试程序的代码
本程序用于测试本实验
1. 参数说明:
(1) 用 AH 寄存器传递功能号:0 表示读,1 表示写。
(2) 用 DX 寄存器传递要读写的扇区的逻辑扇区号。
(3) 用 es:bx 指向存储读出数据或写入数据的内存区。
2. 程序执行结果:
测试执行的 int 13h 中断例程,将软盘 A 中的数据写入指定的 dat2 段内存区域的操作,其返回 (ah)=0 说明该操作是成功的,且经 Debug 单步执行查看该段位置数据,正是预期的字符串数据。但若将其写入显存,则虽然 (ah)=0 说明操作成功,但屏幕显示却并非预期字符串数据;Debug 单步执行查看,该显存位置的数据也与预期字符串数据不一致 —— 参看下面的方法二的代码。
方法一
assume cs:code
; 操作对象:字符串数据
dat1 segment
db 'Welcome to Masm!',496 dup (0)
dat1 ends
dat2 segment
db 512 dup (0)
dat2 ends
code segment
; 将 dat1 段字符串数据写入到软盘 A 的 0 面、0 道、1 扇区
start: mov ax,dat1
mov es,ax
mov al,1 ; 读取或写入字符串的扇区数为 1 个扇区
mov ah,1 ; 先将字符串数据写入指定软盘的逻辑扇区
mov bx,0 ; 令 es:bx 指向 dat1 段字符串首地址
mov dx,0 ; 读、写的软盘逻辑扇区为 0,即软盘 A 的 0 面、0 道、1 扇区
int 7Ch
; 读取软盘 A 的逻辑扇区 0 处的字符串数据到 dat2 段 512 个内存区域
mov ax,dat2
mov es,ax
mov bx,0 ; 令 es:bx 指向 dat2 段内存区域
mov al,1 ; 读取或写入字符串的扇区数为 1 个扇区
mov ah,0 ; 读取软盘的逻辑扇区字符串数据到 dat2 段
mov dx,0 ; 读、写的软盘逻辑扇区为 0,即软盘 A 的 0 面、0 道、1 扇区
int 7Ch
; 将从软盘扇区中读到 dat2 段内存单元的字符串数据显示在屏幕上,以验证程序操作是否成功
mov ax,0B800h
mov ds,ax
mov si,8*160+29*2 ; 8 行 30 列
mov di,0
mov ah,2 ; 显存属性:绿色字体
show: cmp byte ptr es:[di],0
je shend
mov al,es:[di]
mov [si],ax
inc di
add si,2
jmp show
shend: nop
mov ax,4C00h
int 21h
code ends
end start
方法二
assume cs:code
; 操作对象:字符串数据
data segment
db 'Welcome to Masm!',496 dup (0)
data ends
code segment
; 将 data 段字符串数据写入到软盘 A 的 0 面、0 道、1 扇区
start: mov ax,data
mov es,ax
mov al,1 ; 读取或写入字符串的扇区数为 1 个扇区
mov ah,1 ; 先将字符串数据写入指定软盘的逻辑扇区
mov bx,0 ; 令 es:bx 指向 data 段字符串首地址
mov dx,0 ; 读、写的软盘逻辑扇区为 0,即软盘 A 的 0 面、0 道、1 扇区
int 7Ch
; 读取软盘 A 的逻辑扇区 0 处的字符串数据到显示缓冲区 0 页 8 行 30 列
mov ax,0B800h
mov es,ax
mov bx,7*160+29*2 ; 令 es:bx 指向显示缓冲区 0 页 8 行 30 列
mov al,1 ; 读取或写入字符串的扇区数为 1 个扇区
mov ah,0 ; 读取软盘的逻辑扇区字符串数据到屏幕上
mov dx,0 ; 读、写的软盘逻辑扇区为 0,即软盘 A 的 0 面、0 道、1 扇区
int 7Ch
mov ax,4C00h
int 21h
code ends
end start