zoukankan      html  css  js  c++  java
  • BIOS 扩展 INT 13

    上篇知道,通过BIOS的INT 13中断服务程序,可以访问磁盘,参数是读取扇区的起始磁道号、磁头号、扇区号,读取的扇区个数,缓冲区位置等。

    由于原因:

    BIOS通过USB总线(2.0的是通过EHCI USB)向USB存储设备发送UFI指令来和它进行交流的。
    其中MODE SENSE Command(5AH)就是你所说的媒体介质、模式检测功能,在返回的数据包中包含了一个Media Type and Write Protect块里面有介质描述符的字节(该字节在格式化的UFI命令包中可以指定),BIOS就是根据这个来确认U盘的类型和是否有写保护等。
    系统对USB存储设备访问是采用一种叫LBA的地址(目前采用的是LBA28),并没有所谓的CHS,windows、linux等访问USB存储设备的时候并不使用BIOS的INT 13H,而是通过USB总线直接发UFI命令包,采用的地址也是LBA,所以就不太存在兼容性问题。
    然而U盘启动引导程序确是依靠BIOS的INT 13H来访问。
    BIOS的INT 13H对U盘的支持(不一定支持),就是把INT 13H中的C、H、S参数转化成LBA地址,然而不同的BIOS设定的每道扇区数、每头柱面数并不一定相同。假设我们有个U盘在自己机子的BIOS被认成16H、512C、64S,分区格式化后,分区的开始位置为0H、1CH、1S,分区引导程序所在的LBA是0000064H,另一台机子的BIOS认成16H、1024C、32S,那么我们刚才做的那个启动盘,分区起始扇区的LBA就变成0000032H,很显然位置错了,当然启动不起来了。
    BIOS对每道扇区数、每头柱面数的不同设置就是导致U盘启动不通用的根本原因。
    也许你会说那么我们引导程序干脆直接使用扩展INT 13H发送LBA包,GRUB就是这种思路,可是有的BIOS并不支持U盘的扩展INT 13H功能,并且在检测的时候还会返回支持的假象-_-!!
    其实386时代的硬盘也遇到这个问题,然而当时CMOS里面提供了硬盘类型参数的手动设置,再加上硬盘不是移动存储设备,所以问题就没那么明显了。
    至于HDD、FDD、ZIP只是媒体介质描述的不同,并不能彻底解决CHS问题。

    (来自:http://bbs.wuyou.com/forum.php?mod=viewthread&tid=127538

    BIOS设计者设计了INT 13的扩展功能,使得磁盘操作更简单、有效。

    原理介绍可以参考:http://xiepeng63648789.blog.163.com/blog/static/4847149120097493827305/

    我的代码:

    org 07c00h
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ah,0x42
    mov dl,80h
    mov si,packet
    sub bx,bx
    int 0x13
    jnc OK
    mov ax,WrongMessage
    mov bp,ax
    mov cx,31
    mov ax,01301h
    mov bx,000ch
    mov dl,0
    int 10h
    jmp $
    OK:
    mov ax,07e0h
    mov es,ax
    mov ax,0000h
    mov bp,ax
    mov cx,512
    mov ax,01301h
    mov bx,000ch
    mov dl,0
    int 10h
    jmp $
    WrongMessage: db "I am sorry. why not try again?"
    packet:
    packet_size: db 10h
    reserved: db 00h
    count: dw 0002h
    bufferoff: dw 0000h
    bufferseg: dw 07e0h
    blockNum: dq 01h
    times 510-($-$$) db 0
    dw 0xaa55

    先准备一个数据结构,作为中端服务程序的参数,里面指定读取扇区的起始地址(线性地址更直接、简单),扇区个数,缓冲区地址。

    代码不足就是,该参数数据结构在中断调用完就没用了,相当于函数调用里面的局部变量,可以使用堆栈,在使用前把参数依次压入堆栈,中断服务程序到堆栈中去取参数,服务完后,再sp+len,使得空间仍可以继续使用。当我们不知道函数参数具体多少时,常用的技巧:

    压入参数前

    push bp

    mov bp sp(记录当前位置)

    push .....push(压入参数)

    call ..(服务执行)

    mov sp,bp(不管压入多少参数,SP都回到了以前的状态)

    pop bp 

    (关于函数调用,到底压入堆栈的参数由谁处理,可以是中断处理函数,因为它自己本身知道自己用的参数个数是多少,方便处理,另外由函数的调用者用上面的办法处理,这是C语言里面的两个约定)

    我的代码:

    org 07c00h
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,7a00h
    push bp
    mov bp,sp
    push 00h
    push 00h
    push 00h
    push 00h
    push 00h
    push 00h
    push 00h
    push 02h
    push 00h
    push 00h
    push 7eh
    push 00h
    push 00h
    push 02h
    push 00h
    push 10h
    mov ah,0x42
    mov dl,80h
    mov si,sp
    int 0x13
    mov sp,bp
    pop bp
    jnc OK
    mov ax,WrongMessage
    mov bp,ax
    mov cx,30
    mov ax,01301h
    mov bx,000ch
    mov dl,0
    int 10h
    jmp $
    OK:
    mov ax,7e00h
    mov bp,ax
    mov cx,512
    mov ax,01301h
    mov bx,000ch
    mov dl,0
    int 10h
    jmp $
    WrongMessage: db "I am sorry. why not try again?"
    times 510-($-$$) db 0
    dw 0xaa55

    比较好的帖子或博客:

    http://bbs.csdn.net/topics/10186108
    http://www.mouseos.com/win7/int_0x13.html
    http://blog.csdn.net/sunny_unix/article/details/7220162
    http://zenhumany.blog.163.com/blog/static/1718066332011111224018552/
    http://wenku.baidu.com/link?url=U_iF5JdqbhfHNNw7jGwvJi5e3W31AazQLeDJPY1MHi04REjnFoo3zoqLZzx4OS8g6Fp_vdOpexrcA96cle0UPmBHMhs7D91wux_c39qu92q
    http://xiepeng63648789.blog.163.com/blog/static/4847149120097493827305/

  • 相关阅读:
    有几个PAT
    数组模拟求阶乘
    从程序员到架构师转变
    [评论]去360还是留在百度?
    PHPCMS V9模板制作进阶教程之常用PC标签大全
    phpcms v9 如何用PC标签在列表页中同时调出文章内容
    PHP创建缩略图造成图片质量低下的完美解决方法
    Jquery关闭离开页面时提醒
    天猫启动了旗舰店升级品牌商城计划 天猫商城旗舰店向自主B2C模式转型
    shopex模板编辑说明文档
  • 原文地址:https://www.cnblogs.com/zeng2013/p/3637864.html
Copyright © 2011-2022 走看看