2016-12-06 10 views
3

私のブートローダの第2段階で、仮想フロッピーディスクの一部のセクタをbochsのメモリにロードしようとしていますが、int 0x13を呼び出すと、戻ることはありません。フロッピーリード(AH = 0x2、int 0x13)が完了しない

私は私の第二段階から関連するコードがあると信じて:

bootsys_start: 
    mov %cs, %ax 
    mov %ax, %ds 

    /* 
    * Remap IRQs. Interrupts have been disabled in the 
    * bootloader already. 
    */ 

    mov i8259A_ICW1($i8259A_IC4), %al 
    out %al, i8259A_ICW1_ADDR($i8259A_MASTER) 
    out %al, i8259A_ICW1_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW2($USER_INT_START), %al 
    out %al, i8259A_ICW2_ADDR($i8259A_MASTER) 
    mov i8259A_ICW2($USER_INT_START + 8), %al 
    out %al, i8259A_ICW2_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW3($0x4), %al 
    out %al, i8259A_ICW3_ADDR($i8259A_MASTER) 
    mov i8259A_ICW3($0x2), %al 
    out %al, i8259A_ICW3_ADDR($i8259A_SLAVE) 

    mov i8259A_ICW4($i8259A_uPM & i8259A_x86), %al 
    out %al, i8259A_ICW4_ADDR($i8259A_MASTER) 
    out %al, i8259A_ICW4_ADDR($i8259A_SLAVE) 

    call mm_detect 

    /* Load the kernel now. */ 

    xor %bp, %bp 
1: 
    mov $KERNEL_ORG >> 0x4, %ax 
    mov %ax, %es 
    mov $KERNEL_ORG & 0xf, %bx 
    mov $0x200 | KERNEL_SECTORS, %ax 
    mov $(KERNEL_C << 0x8) | KERNEL_S, %cx 
    mov $(KERNEL_H << 0x8) | FLOPPY_DRV, %dx 
    int $0x13 /* <--- This int 0x13 doesn't seem to return */ 
    jnc 1f 
    cmp $0x2, %bp 
    je floppy_err 
    inc %bp 
    xor %ah, %ah 
    int $0x13 
    jmp 1b 

コードのすべてが私のGithub repositoryで見つけることができます。私がやったコマンドにbochs


を使用してBOCHSを make allを使用して、 で実行

を構築するにはまず最初は、私は本当にすべてのパラメータが右まし検証されました。

CPU0: 
rax: 00000000_534d0201 rcx: 00000000_00000005 
rdx: 00000000_534d0000 rbx: 00000000_00000000 
rsp: 00000000_00007700 rbp: 00000000_00000000 
rsi: 00000000_000e0005 rdi: 00000000_00000316 
r8 : 00000000_00000000 r9 : 00000000_00000000 
r10: 00000000_00000000 r11: 00000000_00000000 
r12: 00000000_00000000 r13: 00000000_00000000 
r14: 00000000_00000000 r15: 00000000_00000000 
rip: 00000000_00000036 
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf 

ah = 0x2(ルーチンID)、al = 0x1(セクタ数)、ch = 0x0(シリンダ番号の下位バイト)、cl = 0x5(セクター番号およびシリンダなしの高い2ビット):Bochsのシェル収率でrdh = 0x0(ヘッド番号)、dl = 0x0(ドライブ番号)。

sreges用印刷物:

es:0x0000 

bx = 0x0、その部門は、私が意図したのと同様に、0x0:0x0にロードされます。


、私はいくつか試してみました:私は多分IVTまたはBDAを上書きすることは割り込みルーチンBIOSの実行中に、良いアイデアではないかもしれないと思った0x600

物理アドレスに

  1. ロード私はセクタを0x600es = 0x60bx = 0x0)にロードしようとしました(BDAのサイズは256バイトのみです)。同じ結果。

  2. たぶん第五部門を読ん

    が範囲または任意の外に何らかの形で?ディスクの最初のセクターをロードしますかint 0x13を使用して私の第2段階を読むコードは、期待通りに機能します。私の第2段階のint 0x13は似ているので、私はそれがうまくいくと期待していました。テストとして、私はセクター1を読むために私の第2ステージを変更しましたが、それでも動作しませんでした。私は考え出しeax

    の上部をゼロ

  3. は多分確かにBIOSルーチンにバグがあり、何とかeaxaxを使用していません。私はeaxの上位16ビット部分をゼロにしてみました...無駄です。

私はすでに前に言ったように、私はすでにメモリにディスクからいくつかのセクターをロード。(Bochsのシェルでrを用いて得られた)次のようにint 0x13前のGPRのコンテンツ権利がある:

CPU0: 
rax: 00000000_00000203 rcx: 00000000_00090002 
rdx: 00000000_00000000 rbx: 00000000_00000000 
rsp: 00000000_00007700 rbp: 00000000_00000000 
rsi: 00000000_000e7cdd rdi: 00000000_000000e2 
r8 : 00000000_00000000 r9 : 00000000_00000000 
r10: 00000000_00000000 r11: 00000000_00000000 
r12: 00000000_00000000 r13: 00000000_00000000 
r14: 00000000_00000000 r15: 00000000_00000000 
rip: 00000000_00007c59 
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf 

sreg

右EBDA前に動的に計算されたアドレスであるes:0x8f60をもたらします。両方を比較

、私は割り込みルーチンの機能に影響を与える可能性がある有意な差が表示されないので、問題はレジスタを介して渡されたパラメータにすることはできません。

他に何をすべきか提案がありますか?私は一種のあなたのInt 13h/AH=02hフロッピーディスク読み取りコードに...ここ

+1

あなたは[MCVE]で問題を分離しようとしたことがありますか?具体的には、IPが最初のケースで36h、2番目のケースで7c59hであることを考慮してセグメントレジスタを設定する方法。 –

+0

"セクタが0x0:0x0にロードされるので、エラーベクタテーブルを上書きしますか? – davmac

+0

@MargaretBloom 'cs'は、前者は' 0x8f60'、後者は '0x0'です。 BIOSはブートローダを物理アドレス0x7c00にロードし、ブートローダはEBDAの直下の第2ステージブートローダをロードします。その値は動的に取得され、第2ステージブートローダはカーネルを物理アドレス0x0にロードします。私はMCVEをして、ロードセクタが** no **試みが成功した場合に一般的に動作することを確認します。しかし、セカンダリブートローダをロードするだけでうまくいきます。 – Downvoter

答えて

6

問題のカップルを失っています:

  1. すでにあなたの質問に特定され、この1。リアルモードで実行しているときに0x0000:0x0000の上にセクタを読み込むのは悪い考えです。割り込みベクタテーブル(IVT)が壊れてしまいます。 0x0000:0x0000から0x0040:0x0000までの領域がIVTです。領域0x0040:0x0000〜0x0060:0x0000はBIOS Data Area(BDA)です。 BDAは、リアルモードBIOSルーチンが使用できるスクラッチ領域と見なす必要があります。

    0x0060:0x0000(物理アドレス0x00600)のようにどこか安全にロードするように修正します。

    いったんプロテクトモードで0x00000000のと0x00000600との間の領域は、他の用途のために再利用することができます。 System Management Mode(SMM)とAdvanced Configuration and Power Interface(ACPI)がそれに書き込み可能性があるため、汎用メモリとしてExtended BIOS Data Area(EBDA)メモリ領域を使用しないでください。

  2. あなたのコードは、保護モードの準備をするために8259Aを再マップします。その際、IRQはIVTの異なる部分に再マッピングされます。 Int 13hルーチンは、フロッピーディスクの読み取りに必要な作業を実行するために、割り込みの割り込みとBIOS割り込みルーチンに依存している場合があります。 IRQ0(システムタイマ)とIRQ6(フロッピーコントローラ)が可能です。 8259Aのベースを別の場所に再マップすると、BIOSによってインストールされた割り込みルーチンは実行されません。これにより予期しない動作が発生する可能性があります。これにはInt 13hが返されません。この問題を解決するには

    、私はあなたがプロテクトモードである後8259Aの写真のベースを再マッピングをお勧めします。その時までには、BIOS割り込みが発生する可能性が高いので、問題ではありません。

関連する問題