开机启动时对软驱的访问
我写了一个开机的boot刷入软驱中,让它引导读取其他扇区的代码再执行,
但总是莫名其妙的死在那里(在虚拟机里做的实验)不往下执行指令.
我用的是int 13h的bios中断服务, 用2号读取到0:200那里, 再跳到那里执行.
但似乎总卡死再读扇区那里,也不返回错误代码,也不往下执行.
boot的读取扇区的前面的显示提示信息的代码执行的没问题...
看代码吧!
- Assembly code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; BIOS下;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 括号是我测试后的结果, 我是在dos下把下面代码写到0软驱0面0磁道1扇区的; 又把待执行代码写到2扇区, 开机floppy先启动;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>bootsg segment org 7c00h_main proc mov ax,cs mov ss,ax lea bp,BufferTop;********************************************************** mov ax,cs ; 显示Msg1 mov es,ax mov bp,offset Msg1 mov bx,000ch mov cx,Msg1Len xor dx,dx mov al,1 mov ah,13h int 10h ; (能显示执行!!);********************************************************** mov ah,1 ; 读取磁盘状态 xor al,al mov dl,1 int 13h jmp disp ; 显示AL的值 (测试过了,00,没问题!);**********************************************************back: mov ax,cs ; 显示Msg1 mov es,ax mov bp,offset Msg1 mov bx,000ch mov cx,Msg1Len mov dx,0200h mov al,1 mov ah,13h int 10h ; (还能执行!!);********************************************************** mov ax,0 mov es,ax ; 读到0:200h mov bx,100h mov al,1 ; 传输的扇区数 mov ch,0 ; 磁道号 mov cl,2 ; 扇区号 mov dx,0 ; 磁头号, 驱动号 mov ah,2 ; 读 int 13h ; (似乎卡死在这里了,下面的代码都没动!!);********************************************************** mov ax,cs ; 显示Msg2 mov es,ax mov bp,offset Msg2 mov dx,0300h mov bx,000ch mov cx,Msg2Len mov ah,13h mov al,1 int 10h;********************************************************** mov ah,10h ; 读任意一个字符 int 16h lea bx,Entry jmp far ptr cs:[bx] ; 开始待执行程序disp: mov bl,al ; 显示al代码 mov ah,0 mov cl,4 shr al,cl call ToASCII call EchoChar push ax ; 向前移动光标 push bx push dx mov ah,3 mov bh,0 int 10h inc dl mov ah,2 int 10h pop dx pop bx pop ax mov al,bl and al,00001111b mov ah,0 call ToASCII call EchoChar jmp back_main endp;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 将AL的低4位转换为ASCII字符。例如:0ah -> 41h、41h -> 31h;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ToASCII proc ; 解释: ; 如果al的低4位小于等于9,第一个daa不变,然后 ; 90+40,第二个daa把高4位调整为3 ; 如果al的低4位大于9,第一个daa调整把高4位清0, ; adc在为低位加41 and al,0fh add al,90h daa adc al,40h daa retToASCII endp;**********************************************************; 打印al的ASCII字符;**********************************************************EchoChar proc uses ax bx cx mov ah,0ah mov bx,000ch mov cx,1 int 10h retEchoChar endp;**********************************************************Entry dw 200h, 0;**********************************************************Msg1 db 'Boot have loaded!!',0dh,0ahMsg1Len = $ - Msg1Msg2 db 'Copy OK!',0dh,0ah db 'Starting test !(press any key!)',0dh,0ahMsg2Len = $ - Msg2MsgErr2 db 'Read Error !',0dh,0ahMsgErr2Len = $ - MsgErr2;**********************************************************Buffer dd 50 dup (?)BufferTop label byte dw 0aa55h ; 结尾BootLen = $ - _main ; 小于512bootsg ends
最后说一句, 我把它单独提取出来在dos中测试了一下, 执行一点问题都没!
[解决办法]
实模式下 00000- 003FF 是中断向量表(IVT)
你把磁盘内容读取到这里就覆盖了中断向量表,破坏了中断系统,之后再去调用中断的话,根本找不到正确的中断服务程序的入口了。
mov al,1 ; 传输的扇区数
mov ch,0 ; 磁道号
mov cl,2 ; 扇区号
mov dx,0 ; 磁头号, 驱动号
mov ah,2 ; 读
int 13h ; (似乎卡死在这里了,下面的代码都没动!!)
;**********************************************************
mov ax,cs ; 显示Msg2
mov es,ax
mov bp,offset Msg2
mov dx,0300h
mov bx,000ch
mov cx,Msg2Len
mov ah,13h
mov al,1
int 10h ===========真正的卡死实在这里,中断向量表已经损坏,根本找不到中断服务程序入口,所以程序已经跑飞了。
我看很多人都说看王爽的书,没看过这本书,也不知道他是谁。
启动后 bios自动调用IINT 19H 把bootsector加载到07c00h,后面的secondary boot代码是自己负责放置在内存的何处,我想王爽的书里面可能是bootsector先自己把自己复制到别处,然后把段地址es设置为07c00<<16的值出,然后把secondary boot代码拷贝到es:00h 到 es:200h处吧。
可以看看我整理的资料。
http://blog.csdn.net/otishiono/article/details/5906119