《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程
- 逻辑扇区
- 根据逻辑扇区号算出物理编号
- 中断例程:通过逻辑扇区号对软盘进行读写
- 代码
- 安装 int 7ch
- 测试程序
- 效果
实现通过逻辑扇区号对软盘进行读写
逻辑扇区
计算公式: 逻辑扇区号 =(面号*80+磁道号)*18+扇区号-1
let lg = (面, 道, 扇区) => (面*80+道)*18+扇区-1;
lg(1,60,10); // 2529
// 创建一个空数组来存放所有的逻辑扇区号
let logicalSectors = [];
// 遍历指定范围的所有组合
for (let head = 0; head <= 1; head++) { // 面号从0到1
for (let track = 0; track <= 79; track++) { // 磁道号从0到79
for (let sector = 1; sector <= 18; sector++) { // 扇区号从1到18
logicalSectors.push([head,track,sector]);
}
}
}
// 输出所有逻辑扇区号(索引就是逻辑扇区号)
console.table(logicalSectors);
面 | 道 | 扇区 | 逻辑扇区 |
---|---|---|---|
0 | 0 | 1 | 0 |
↓ | ↓ | ↓ | ↓ |
1 | 79 | 18 | 2879 |
根据逻辑扇区号算出物理编号
物理编号 | 公式 |
---|---|
面号 | 取商( 逻辑扇区号 / 1440 ) |
磁道号 | 取商( 取余( 逻辑扇区号 / 1440 ) / 18 ) |
扇区号 | 取余( 取余( 逻辑扇区号 / 1440 ) / 18) + 1 |
中断例程:通过逻辑扇区号对软盘进行读写
功能 | 通过逻辑扇区号对软盘进行读写 |
---|---|
参数 | ah = 功能号:0 =读,1 =写;dx = 逻辑扇区号;es:bx =用于读写的缓冲区 |
代码
安装 int 7ch
assume cs:code
code segment
start: ; ---------------- 安装(复制数据) ----------------
mov ax,cs
mov ds,ax
mov si,offset i7ch ;设置 ds:si 指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置 es:di 指向目的地址
mov cx,offset i7chend -offset i7ch ;设置 cx为传输长度
cld ;设置传输方向为正。movsb中si,di递增
rep movsb ;重复复制数据次数由 cx 控制
; ---------------- 安装(复制数据) ----------------
; ----------------- 设置中断向量 -----------------
mov ax,0
mov es,ax ; 段地址 0
mov word ptr es:[7ch*4],200h ; 设置【中断处理程序】的:偏移地址
mov word ptr es:[7ch*4+2],0 ; 设置【中断处理程序】的:段地址
; ----------------- 设置中断向量 -----------------
mov ax, 4c00H ; 退出
int 21H ; 触发33号中断
; =======================================================
; --------------------- 中断处理程序 --------------------
; 通过逻辑扇区号对软盘进行读写
; -------------------------------------------------------
; 参数:ah = 功能号:0=读,1=写;
; 参数:dx = 逻辑扇区号;
; 参数:es:bx = 用于读写的缓冲区
; -------------------------------------------------------
org 200h ; ORG 指定下面代码从一个特定地址开始编译
i7ch: push dx ; 备份寄存器
cmp ah,1 ; 功能号>1直接退出
ja i7chok
call logical2physical ; 算出物理:面号、磁道号、扇区号
mov dl,0 ; 驱动器号 A盘
mov al,8 ; 读写扇区数
cmp ah,0
je read ; 读跳 read
jmp write ; 否则跳 write
read:
mov ah,02h
int 13h
jmp i7chok
write:
mov ah,02h
int 13h
i7chok: pop dx ; 还原寄存器
iret ; 返回原程序
; --------------------- 中断处理程序 --------------------
; =======================================================
; =======================================================
; --------------------- 中断处理程序 --------------------
; 根据逻辑扇区号算出物理编号
; -------------------------------------------------------
; 参数:dx = 逻辑扇区号
; 返回:dh = 面号 01
; 返回:ch = 磁道号 06
; 返回:cl = 扇区号 109
; -------------------------------------------------------
logical2physical:
jmp short l2ph_start
hts dw 1440, 18
l2ph_start:
push ax ; 备份寄存器
push bx
mov ax,dx
mov dx,0
; 逻辑扇区号 / 1440:商ax = 面号,余数dx拿去算:磁道号、扇区号
div word ptr hts[0] ; 除以 1440
mov bx,ax ; 面号(临时保存)
; dx / 18:商al = 磁道号,余数ah + 1 = 扇区号
mov ax,dx
div byte ptr hts[2] ; 除以 18
mov ch,al ; 磁道号
inc ah
mov cl,ah ; 扇区号
mov dh,bl ; 面号
pop bx ; 还原寄存器
pop ax
ret ; 返回原程序
; --------------------- 中断处理程序 --------------------
; =======================================================
i7chend: nop
code ends
end start
测试程序
assume cs:code
data segment
arr db 4000 dup(0)
data ends
code segment
start:
mov ax,data
mov es,ax
mov bx,offset arr
mov ah,0
mov dx,0
int 7ch
ok: mov ax,4c00h
int 21h
code ends
end start
效果
int 13h 读写始终失败,DOSBox 和 VMware上装的 DOS7.10 都试过了。暂时没想到办法
DOSBox
虚拟机上DOS