分享

学习x86汇编语言7 使用INT13读取软盘数据

 启云_9137 2020-08-22
学习x86汇编语言7 使用INT13读取软盘数据

一、本章使用工具

  • nasm
  • FloppyWriter
  • bochs

二、软盘存储介绍

  • 1.44M的软盘有2面
  • 每面80个柱面(簇)
  • 一个柱面18个扇区
  • 每个扇区有512字节
学习x86汇编语言7 使用INT13读取软盘数据
学习x86汇编语言7 使用INT13读取软盘数据

总容量:280×18×512=1474560(字节)280 \times 18 \times 512=1474560(字节)280×18×512=1474560(字节)

三、BIOS int13功能

BIOS的int13 中断是扩展的磁盘读取功能。入口参数:

  • ah= int 13H 的功能号(2表示读扇区、3表示写扇区)
  • al= 读取/写入的扇区数
  • ch= 磁道号
  • cl= 扇区号
  • dh= 磁头号(对于软盘即面号,对软盘一个面用一个磁头来读写)
  • dl= 驱动器号 软驱从0开始,0:软驱A 、 1:软驱B硬盘从80H开始,80H:硬盘C 、 81H: 硬盘D

es:bx 指向接收从扇区读入数据的内存区/指向将写入磁盘的数据

返回参数:

  • 操作成功,(ah)= 0 ,(al)= 读取/写入的扇区数
  • 操作失败,(ah)= 出错代码

一段写磁盘示例读屏幕到软盘上,1屏4000Byte,使用8个扇区,使用磁盘的0面0道1~8扇区存储。

assume cs:codecode segment start: mov ax,0B800h mov es,ax mov bx,0 mov al,8 mov ch,0 mov cl,1 mov dl,0 mov dh,0 mov ah,3 int 13h mov ax,4c00h int 21H code ends end start

一段读磁盘示例读0面0道1扇区到 0000:0200H

assume cs:codecode segment    start:  mov ax,0            mov es,ax            mov bx,200H                        mov al,1            mov ch,0            mov cl,1            mov dl,0            mov dh,0            mov ah,2            int 13h                        mov ax,4c00h            int 21H    code ends    end start

四、引导程序源代码

  • 带读磁盘的功能,把磁盘数据加载到内存的 0x0820处。
  • 从第2个扇区开始读,因为第一个扇区给启动程序用了。
;%define _BOOT_DEBUG_ ; 做Boot Sector时把这行注释掉 ; 启用这行就用nasm Boot.asm -o Boot.com生成.com文件用于调试%ifdef _BOOT_DEBUG_ org 0100h%else org 07c00h%endifCYLS EQU 10init: MOV AX,0 MOV SS,AX MOV SP,0x7c00 ; 堆栈空间,从0x7c00向前 MOV DS,AX MOV AX,0x0820 ; 把磁盘数据加载到内存0x0820处。 0x8000~0x81ff的512字节给启动区用的,所以从0x0820开始 MOV ES,AX ; 初始化磁盘接口 MOV CH,0 ; 柱面 0 MOV DH,0 ; 磁头 0 MOV CL,2 ; 扇区 2readloop: MOV SI,0 ; 记录失败次数retry: MOV AH,0x02 ; 0x02 读磁盘 MOV AL,1 ; 读1个扇区 MOV BX,0 MOV DL,0x00 ; A驱动器 INT 0x13 ; BIOS 读磁盘功能 JNC next ; 成功跳转 ADD SI,1 ; 失败加一次 CMP SI,5 ; 到5次就跳到error JAE error MOV AH,0x00 ; 复位磁盘功能 MOV DL,0x00 INT 0x13 ; 重置磁盘驱动器 JMP retry ; 重试 next: MOV AX,ES ; 内存地址向后移动0x0020 ADD AX,0x0020 MOV ES,AX ; 通过AX给ES加0x0020 ADD CL,1 ; 扇区+1 CMP CL,18 ; 有没有到18个扇区 JBE readloop ; CL<=18,就跳到 readloop MOV CL,1 ADD DH,1 CMP DH,2 JB readloop ; 如果 DH < 2 ,则跳到readloop MOV DH,0 ADD CH,1 CMP CH,CYLS JB readloop ; 如果CH<CYLS , 则跳到readloop JMP successprint: # 字符串显示到屏幕 MOV AL, [SI] ADD SI, 1 CMP AL, 0 JE end MOV AH, 0x0e MOV BX, 15 INT 0x10 JMP printend: HLT JMP end ; 无限循环error: ; 打印错误信息 MOV SI, error_msg JMP printsuccess: MOV SI, success_msg JMP printBootMessage: DB 'Hello, MY OS!' ; 想要开机后在屏幕上显示的字符串 DB 0success_msg: DB 'Success' ; 成功 DB 0error_msg: DB 'Error' ; 失败 DB 0 times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节 $$表示一个section的开始处汇编后地址 DW 0xaa55 ; 结束标志

启动后如无异常屏幕只会显示Success。后面章节再加载主体程序。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多