2

これが私のブートローダーコードであり、これがレジスターの写真(私が間違っていることに重要な場合)、場所0x10000(ブートローダーにカーネルをロードするように指示した場所)のメモリにあったものを示すドキュメントですカーネルのソースアセンブリ、およびQemuの実行時の画面出力。

kernelStub.binには、最初にEB 1B(右ジャンプコマンド)があります。hda.imgには、2番目のセクターの開始時に55AAの直後にEB1Bがあります。キャリーフラグは、load_memサブルーチンでクリアされており、ロードが良好であると信じていることを示しています。最初の2つが常に6361であることを除いて、すべてのバイトはメモリ内にあります。

load_memルーチンが常にセクター2の最初の2バイトをアドレス0x10000に誤ってロードし、残りを正しくロードするのはなぜですか?

ブートローダーコード:

更新:MatthewSlatteryの修正ごとに変更jmp SYSADDR:0000されました。jmp 0x1000:0x0000

;Very minimal boot loader 
BITS 16                ;Tell assembler to use 16-bit mode
jmp start              ;Jump over defines
SYSADDR  dw 0x1000     ;Load system at 0x10000
DRIVENUM db 0x80       ;Variable for drive number
HEADNUM  db 0
CYLNUM   db 0          ;Low bits of cylinder number
SECTNUM  db 2          ;Bits 6 and 7 high bits of cylinder number (0),
                       ;Bits 0-5 starting sector number (2)
NUMKERNELSECTS db 0x01 ;Will Probably Change! Number of sectors
                       ;to read from disk
load_msg    db 'Loading OS', 0
msg_2       db 'carry flag not clear', 0
load_worked db 'Load worked', 0

start:
    mov ax, 0x07C0     ;Set data segment to where BIOS loaded boot loader
    mov ds, ax
    mov si, load_msg   ;Simple text string to indicate loading
    call show_message
    call load_mem      ;Subroutine to load bytes from disk to location
                       ;pointed to by es
    jmp 0x1000:0x0000

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Subroutines

;;;Show Message;;;
show_message:
    mov ah, 0x0E       ;int 0x10 print character to screen function
.repeat:
    lodsb              ;Get char pointed to by si, puts in al
    cmp al, 0          ;see if char is 0 (null)
    je .done           ;null signifies done
    int 0x10           ;If not null, print to screen
    jmp .repeat        ;Get next char

.done:
    ret

;;;Load Memory;;;
load_mem:
    xor ah, ah         ;ah=0, reset drive
    int 0x13           ;Call drive reset

    mov ax, [SYSADDR]
    mov es, ax         ;Destination- es:bx
    mov bx, 0
    mov dl, [DRIVENUM]
    mov dh, [HEADNUM]
    mov al, [NUMKERNELSECTS]
    mov ch, [CYLNUM]
    mov cl, [SECTNUM]
    mov ah, 0x02       ;ah=2, read drive
    int 0x13           ;Call read interrupt
    jnc exit           ;If carry flag is clear, exit

exit:
    ret

times 510 - ($-$$) db 0;Pad sector with 0
dw 0xAA55              ;Boot signature
4

2 に答える 2

4
SYSADDR  dw 0x1000    ;Load system at 0x10000
...
jmp SYSADDR:0000

あなたが望むことをしません。 SYSADDR値自体ではなく、必要な値の場所(0x0002ここ)です。

たまたま0x0002:0000(実際のコードではなく、割り込みベクトルテーブルの一部である)何でも実行すると、データが書き留められる原因になると思います。

(ちなみに、少なくとももう1つ問題があります。2番目にリンクされたドキュメントのカーネルスタブコードがリセットされませんds。)


編集:

これで動作しているようですが、完全を期すために、jmp SYSADDR:0000バグの結果として、これら2バイトの不思議な値について完全に説明しています。

0002:0000、つまりアドレス0x20は、のベクトルですINT 08h

INT 08hハンドラーの従来のエントリポイントアドレスは次のとおりですf000:fea5(エントリポイントを直接使用するコードとの互換性のために、BIOSは従来のエントリを維持する傾向があります)。したがって、このアドレスのバイトはほぼ確実にa5 fe 00 f0 ...です。

これらのバイトの最初のバイトa5をコードとして実行すると、それは命令であり、からにmovsw 2バイトをコピーします。ds:sies:di

  • dsまだブートローダーのデータセグメントです
  • simsg_2show_message印刷後にルーチンが残した場所load_msg)の先頭を指します
  • esまだです0x1000
  • diおそらく0が含まれています

したがって、の後に最初に発生するのjmp 0x0002:0000は、 cおよびが最初aからmsg_2ロードされたセクターの最初の2バイトにコピーされることです。

于 2012-06-28T00:08:12.220 に答える
0

ここで、カーネルの最初のジャンプを取得するという私の質問に関する重要な詳細を見つけました。(少なくとも一部のBIOSでは)。を短くすることがどれほど必要かわかりませんでしjmpnop

sを入れてレジスターnopを設定すると、ようやく機能しました。ds

于 2012-06-28T16:27:06.110 に答える