上篇知道,通過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/
