首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

开机启动时对软驱的访问解决方法

2012-02-14 
开机启动时对软驱的访问我写了一个开机的boot刷入软驱中,让它引导读取其他扇区的代码再执行,但总是莫名其

开机启动时对软驱的访问
我写了一个开机的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

热点排行