《汇编语言》- 读书笔记 - 第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到1for (let track = 0; track <= 79; track++) { // 磁道号从0到79for (let sector = 1; sector <= 18; sector++) { // 扇区号从1到18logicalSectors.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 segmentstart: ; ---------------- 安装(复制数据) ----------------mov ax,csmov ds,axmov si,offset i7ch ;设置 ds:si 指向源地址mov ax,0mov es,axmov di,200h ;设置 es:di 指向目的地址mov cx,offset i7chend -offset i7ch ;设置 cx为传输长度cld ;设置传输方向为正。movsb中si,di递增rep movsb ;重复复制数据次数由 cx 控制; ---------------- 安装(复制数据) ----------------; ----------------- 设置中断向量 -----------------mov ax,0mov es,ax ; 段地址 0mov 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 i7chokcall logical2physical ; 算出物理:面号、磁道号、扇区号mov dl,0 ; 驱动器号 A盘mov al,8 ; 读写扇区数cmp ah,0 je read ; 读跳 readjmp write ; 否则跳 writeread:mov ah,02hint 13hjmp i7chokwrite:mov ah,02hint 13hi7chok: pop dx ; 还原寄存器iret ; 返回原程序
; --------------------- 中断处理程序 --------------------
; =======================================================; =======================================================
; --------------------- 中断处理程序 --------------------
; 根据逻辑扇区号算出物理编号
; -------------------------------------------------------
; 参数:dx = 逻辑扇区号
; 返回:dh = 面号 01
; 返回:ch = 磁道号 06
; 返回:cl = 扇区号 109
; -------------------------------------------------------
logical2physical:jmp short l2ph_starthts dw 1440, 18
l2ph_start: push ax ; 备份寄存器push bxmov ax,dxmov dx,0; 逻辑扇区号 / 1440:商ax = 面号,余数dx拿去算:磁道号、扇区号div word ptr hts[0] ; 除以 1440mov bx,ax ; 面号(临时保存); dx / 18:商al = 磁道号,余数ah + 1 = 扇区号mov ax,dxdiv byte ptr hts[2] ; 除以 18mov ch,al ; 磁道号inc ahmov cl,ah ; 扇区号mov dh,bl ; 面号pop bx ; 还原寄存器pop axret ; 返回原程序
; --------------------- 中断处理程序 --------------------
; =======================================================i7chend: nop
code ends
end start
测试程序
assume cs:code
data segmentarr db 4000 dup(0)
data endscode segmentstart: mov ax,datamov es,axmov bx,offset arrmov ah,0mov dx,0int 7chok: mov ax,4c00hint 21h
code ends
end start
效果
int 13h 读写始终失败,DOSBox 和 VMware上装的 DOS7.10 都试过了。暂时没想到办法
DOSBox
虚拟机上DOS