磁盘读写
3.5 英寸软盘分为上下两面,每面有 80 个磁道,每个磁道又分为 18 个扇区,每个扇区的大小为 512 个字节。下面的磁盘读写均以 3.5 英寸软盘为例。
在读写扇区的时候,要给出面号、磁道号和扇区号。面号和磁道号从 0 开始,扇区号从 1 开始。
BIOS提供的访问磁盘的中断例程为 int 13h 。读取软盘 0 面 0 道 1 扇区的内容到 0:200 的程序如下所示:
mov ax,0
mov es,ax
mov bx,200h ;es:bx指向接收/读写扇区的内存区起始地址
mov al,1 ;读取/写入的扇区数目
mov ch,0 ;磁道号
mov cl,1 ;(起始)扇区号
mov dh,0 ;磁头号(对于软盘来说就是面号,因为一个面用一个磁头来读写)
mov dl,0 ;驱动器号: 软驱从 0 开始: 0,软驱 A ; 1,软驱 B。
硬盘从 80h 开始: 80h,硬盘 C ; 81h,硬盘 D 。
mov ah,2 ;int 13h 的功能号(常用的:2 表示读扇区;3 表示写扇区)
int 13h
如果是将 0:200 中的内容写入 0 面 0 道 1 扇区的话,只需要将上面程序稍微改写一下即可:
... ;前面的代码不变
mov ah,3
int 13h
练习:将当前屏幕的内容保存在磁盘上。
分析:一屏的内容占4000个字节,所以需要 8 个扇区。
assume cs:code
code segment
mov bx,0b800h
mov es,bx
mov bx,0
mov al,8 ;需要注意这里更改写入扇区的数目
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h
code ends
end
实验17
编写包含多个功能子程序的中断例程:
想对扇区用逻辑编号来统一表示,具体编号方法如下:
物理扇区号 逻辑扇区号
0 面 0 道 1 扇区 0
0 面 0 道 2 扇区 1
0 面 0 道 3 扇区 2
0 面 0 道 18 扇区 17
0 面 1 道 1 扇区 18
0 面 1 道 2 扇区 19
0 面 1 道 18 扇区 35
0 面 2 道 1 扇区 35
0 面 2 道 2 扇区 36
0 面 2 道 1 扇区 35
…
0 面 79 道 18 扇区 1439
1 面 0 道 1 扇区 1440
可得下面的转换关系: 逻辑扇区号 = (面号 x 80 + 磁道号)x 18 + 扇区号 - 1
由逻辑扇区号得物理扇区号的方法给出如下:
int():取商 rem():取余数
面号 = int(逻辑扇区号/1440)
磁道号 = int(rem(逻辑扇区号/1440)/18)
扇区号 = rem(rem(逻辑扇区号/1440)/18)+ 1
任务:安装一个新的 int 7ch 中断例程,实现通过逻辑扇区号对软盘进行读写。
参数说明:
(1)用 ah 寄存器传递功能号:0 表示读,1 表示写;
(2)用 dx 寄存器传递要读写的扇区的逻辑扇区号;
(3)用 es:dx 指向存储读出数据或写入数据的内存区;
assume cs:code
code segment
start: mov si,cs
mov ds,si
mov si,offset body
mov di,0
mov es,di
mov di,200h
mov cx,offset bodyend-offset body
cld
rep movsb
mov word ptr es:[7c*4],200h
mov word ptr es:[7c*4+2],0
mov ax,4c00h
int 21h
body: jmp short s
t db 3 dup(0) ;用来存放面号,磁道号和扇区号
s: push si
push cx
push bx
push ax
mov ax,dx
mov dx,0
mov bx,1440 ;bx 中存放除数
div bx ;32位/16位
mov si,0
mov byte ptr t[si],al
mov ax,dx
mov bl,18
div bl ;16位/8位
inc si
mov byte ptr t[si],al
inc si
inc ah
mov byte ptr t[si],ah
;至此已将面号,磁道号和扇区号分别存入内存中
;下面进行磁盘读写,默认读取的扇区个数为1
pop ax
pop bx
mov al,1
mov si,1
mov ch,t[si]
inc si
mov cl,t[si]
mov dl,0
mov si,0
mov dh,t[si]
int 13h
pop cx
pop si
iret
bodyend: nop
code ends
end start