利用BIOS指令实现了读磁盘
在大多数情况下,程序只指定读一个扇区或读取一个磁道上的全部扇区。读操作只是顺序读取CH和CL指定的扇区内容,并递增CH和CL中的磁道号和扇区号,如果扇区号超过了磁道的最大扇区号,必须把扇区号重新置1,并把磁道号增1,或者把双面盘的0面变1面。
(1)本程序计算每一个磁盘地址,每次读操作之后,扇区号+1,当扇区号加到10则重新置扇区号为1,如果盘面是1则增加磁道号,然后改变盘面,或由0改为1或由1改为0
(2)数据项CurrentAddr包含起始的磁道/扇面地址,EndAddr包含结束的磁道/扇面地址。
BIOS磁盘操作INT 13H处理的记录都是一个扇区(512 bytes)的大小,都是以实际的磁道号和扇区号寻址的。读,写和检验磁盘文件之前,先把下列寄存器初始化:
AH = 要执行的操作:复位(0), 读状态(1), 读磁盘(2), 写磁盘(3), 检验扇区(4)
AL = 扇区数
CH = 柱面/磁道号(0为起始号)
CL = 起始扇区号(1为起始号)
DH = 磁头/盘面号,对软盘是0或1
DL = 驱动器号: 软盘:0=驱动器A,1=驱动器B,...
硬盘:80h=驱动器1,81h=驱动器2,...
ES:BX = 数据区中I/O缓冲区的地址(除检验操作外)
下面是本程序源代码:
;--------------------------------------------------------------------------------------------------------
; by Loomman, QQ:28077188, MSN: [email protected] QQ裙:30515563
; BiosRd.asm
;--------------------------------------------------------------------------------------------------------
- data segment
- Buffer db 512 dup(' ')
- EndCode db 0
- CurrentAddr dw 0304h ;beginning track/sector
- EndAddr dw 0501h ;Ending track/sector
- ReadErrorMsg db 'Read error!'
- Side db 0
- User db 1, 1 dup(?) ;user input
- data ends
- code segment
- assume cs:code, ds:data
- main proc near
- start:
- push ds
- sub ax, ax
- push ax
- mov ax, data
- mov ds, ax
- mov es, ax
- mov ax, 0600h ;request scroll
- @Continue:
- call ScrollScreen ;Scroll screen
- call SetCursor ;set cursor
- call CalcNextDiskAddr ;calculate next disk address
- mov cx, CurrentAddr
- mov dx, EndAddr
- cmp cx, dx ;is at ending sector?
- je @Exit ;yes, exit
- call ReadDiskRecord ;read disk record
- cmp EndCode, 0 ;normal read?
- jnz @Exit ;no, exit
- call DisplaySector ;display sector content
- jmp @Continue
- @Exit:
- ret
- main endp
- ;calculate next disk address
- CalcNextDiskAddr proc near
- mov cx, CurrentAddr ;get track/sector
- cmp cl, 10 ;pass last sector
- jne @CNDAExit ;no, exit
- cmp Side, 0 ;bypass if Side = 0
- je @ChangeSide
- inc ch
- @ChangeSide:
- xor Side, 1 ;change Side
- mov al, 1 ;set sector to 1
- mov CurrentAddr, cx
- @CNDAExit:
- ret
- CalcNextDiskAddr endp
- ;OUTPUT:
- ;AL = 实际读取的扇区数
- ReadDiskRecord proc near
- mov ah, 2 ;request read
- mov al, 1 ;one sector
- lea bx, Buffer ;input buffer at ES:BX
- mov cx, CurrentAddr ;track/sector
- mov dh, Side ;head 0
- mov dl, 0 ;drive A(Floopy A)
- int 13h ;call BIOS
- cmp ah, 0 ;normal read?
- jz @IncreaseSector ;yes, exit
- mov EndCode, 1 ;no
- call ShowErrorMsg ;invlaid read
- @IncreaseSector:
- inc CurrentAddr ;increase sector
- ret
- ReadDiskRecord endp
- ;display sector
- DisplaySector proc near
- mov ah, 40h ;request display
- mov bx, 1 ;handle
- mov cx, 512 ;length
- lea dx, Buffer ;address of input
- int 21h
- @Wait:
- mov ah, 0ah ;user input
- lea dx, User
- int 21h
- cmp User+1, 0dh
- je @Wait ;wait until user input return
- ret
- DisplaySector endp
- ;clear screen
- ScrollScreen proc near
- mov ax, 0600h ;full screen
- mov bh, 1eh ;set color
- mov cx, 0 ;request scroll
- mov dx, 184fh
- int 10h
- ret
- ScrollScreen endp
- ;set cursor
- SetCursor proc near
- mov ah, 02 ;request set cursor
- mov bh, 0
- mov dx, 0
- int 10h
- ret
- SetCursor endp
- ;disk error function
- ShowErrorMsg proc near
- mov ah, 40h ;request display
- mov bx, 1 ;handle
- mov cx, 11 ;length of message
- lea dx, ReadErrorMsg
- int 21h
- ret
- ShowErrorMsg endp
- code ends
- end start
makefile文件内容如下:
- #NMAKE工具的描述文件
- NAME = BiosRd #指定输出文件
- EXE = $(NAME).exe #需要的EXE文件
- OBJ = $(NAME).obj #需要的OBJ文件
- LST = $(NAME).lst #可选的LST文件
- CRF = $(NAME).crf #可选的CRF文件
- MAP = $(NAME).map #可选的MAP文件
- LIB = NUL.lib #可选的LIB文件
- LINK_FLAG = ,$(EXE),$(MAP),,$(LIB) #链接选项
- ML_FLAG = $(OBJ) $(LST) $(CRF) #编译选项
- #定义依赖关系和执行命令
- $(EXE): $(OBJ)
- Link $(OBJ) $(LINK_FLAG)
- #定义汇编编译和资源编译得默认规则
- .asm.obj:
- masm $< $(ML_FLAG)
- #清除临时文件
- clean:
- del *.MAP
- del *.CRF
- del *.LST
- del *.OBJ
- del *.BAK
- del *.SBR
本程序采用MASM5(或高于此版本)下配合NMAKE编译和链接, 程序已编译通过, 有何问题欢迎联系。by Loomman, QQ:28077188, MSN: [email protected] QQ裙:30515563 ☆程序天堂☆ 请尊重作者原创,转载注明来自裂帛一剑博客,谢谢合作。