2016-09-19 14 views
3

FASM(フラットアセンブラ)を使用してブートローダを作成しています。私は16ビットモードで成功しましたが、私は32ビットモードに切り替える際にエラーに直面しています。私は同様の(infact同じ問題GPF after far jump to protected mode)の答えを見たが、解決策は私の問題を解決しません。保護モードに切り替えて遠くにジャンプするとエラーが発生する

ここに私のブートローダーです -

org 0x7c00 

jmp main 

include 'bios.asm' 
include 'print32.asm' 
include 'gdt.asm' 

main: 

mov bp,0x9000 
mov sp,bp 

mov bx, bootMsg 
call print_string 

lgdt [gdt_descriptor] 
cli 
mov eax, cr0 
or eax, 0x1 
mov cr0, eax 
jmp CODE_SEG:init_pm ;**The error seems to occurs here 

jmp $ 

bits = 32 

init_pm: 
    mov ax,DATA_SEG 
    mov ds,ax 
    mov ss,ax 
    mov es,ax 

    mov ebp, 0x90000 
    mov esp, ebp 
    jmp BEGIN_PM 

BEGIN_PM: 
    mov ebx, pmMsg 
    call print_string32 
    jmp $ 

pmMsg: 
    db "Sucessfully switched to the 32-bit protected mode....",0 

bootMsg: 
    db "Booted in 16-bit Real Mode mode....",0 

times 510-($-$$) db 0 
dw 0xaa55 

ここGDTだ -

gdt_start: 
gdt_null: 
    dd 0x0 
    dd 0x0 

gdt_code: 
    dw 0xffff 
    dw 0x0 
    db 0x0 
    db 10011010b 
    db 11001111b 
    db 0x0 

gdt_data: 
    dw 0xffff 
    dw 0x0 
    db 0x0 
    db 10010010b 
    db 11001111b 
    db 0x0 
gdt_end: 

gdt_descriptor: 
    dw gdt_end - gdt_start - 1 
    dd gdt_start 

CODE_SEG equ gdt_code - gdt_start 
DATA_SEG equ gdt_data - gdt_start 

ハーズは番目のBochsのコンソール出力である -

00478171069i[BIOS ] Booting from 0000:7c00 
00478195765e[CPU0 ] write_virtual_checks(): write beyond limit, r/w 
00478195765e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 
00478195765e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08) 
00478195765i[CPU0 ] CPU is in protected mode (active) 
00478195765i[CPU0 ] CS.mode = 32 bit 
00478195765i[CPU0 ] SS.mode = 32 bit 
00478195765i[CPU0 ] EFER = 0x00000000 
00478195765i[CPU0 ] | EAX=d88e0010 EBX=00007d77 ECX=00090000 EDX=00000000 
00478195765i[CPU0 ] | ESP=00009000 EBP=00000000 ESI=000e0000 EDI=0000ffac 
00478195765i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf 
00478195765i[CPU0 ] | SEG sltr(index|ti|rpl)  base limit G D 
00478195765i[CPU0 ] | CS:0008(0001| 0| 0) 00000000 ffffffff 1 1 
00478195765i[CPU0 ] | DS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00478195765i[CPU0 ] | SS:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00478195765i[CPU0 ] | ES:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00478195765i[CPU0 ] | FS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00478195765i[CPU0 ] | GS:0000(0005| 0| 0) 00000000 0000ffff 0 0 
00478195765i[CPU0 ] | EIP=00007d2f (00007d2f) 
00478195765i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 
00478195765i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 
00478195765i[CPU0 ] 0x0000000000007d2f>> or dword ptr ds:[eax], eax : 0900 
00478195765e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting 

誰もこれで私を助けてくださいことはできますか?

org 0x7c00 

mov bp,0x9000 
mov sp,bp 

mov bx, bootMsg 
call print_string 

cli 
lgdt [gdt_descriptor] 
mov eax, cr0 
or eax, 0x1 
mov cr0, eax 
jmp 0x8:init_pm 

jmp $ 

use32 

init_pm: 
    mov ax, 0x10 
    mov ds, ax 
    mov ss, ax 
    mov es, ax 
    mov fs, ax 
    mov gs, ax 

    mov ebp,0x90000 
    mov esp,0x90000 

    jmp BEGIN_PM 

jmp $ 

include 'bios.asm' 
include 'gdt.asm' 
include 'print32.asm' 

use32 

BEGIN_PM: 
    mov ebx, pmMsg 
    call print_string32 
    jmp $ 

pmMsg: 
    db "Sucessfully switched to the 32-bit protected mode....",0 

bootMsg: 
    db "Booted in 16-bit Real Mode mode....",0 

times 510-($-$$) db 0 
dw 0xaa55 

EDIT - - これは、ここで

編集 -

use32 

VIDEO_MEM equ 0xb8000 
W_O_B equ 0x0f 

print_string32: 
    pusha 
    mov edx,VIDEO_MEM 

print_string32_loop: 
    mov al, [ebx] 
    mov ah, W_O_B 
    cmp al,0 
    je print_string32_end 
    mov [edx],ax 
    inc ebx 
    add edx,2 
    jmp print_string32_loop 

print_string32_end: 
    popa 
    ret 

コード - print32そして、ブートローダのために変更されたコードです。..長いので、私を悩まされていますコードは今作動する!!

+0

Bochsの内部デバッガを使用して、どのフォルトが発生しているかを調べる手順を実行しようとしましたか?私はそれを間違って読んでいるかもしれませんが、保護モードにして、アドレス0x7d2fの 'dword ptr ds:[eax]、eax'のような命令で失敗したようです。 _EAX_はジャンクを含んでいるように見え、ポインタとして使用されており、DSはセグメントセレクタ0に設定されているようですが、0x10と予想されます。 –

+0

あなたの問題には関係しませんが、 'mov bp、0x9000'' mov sp、bp'は実モードスタックポインタを設定する適切な方法ではありません。 _SS_の後にSPを設定する必要があります。スタックを0x0000:0x9000または物理アドレス0x9000にしたい場合は、 'xor ax、ax'' mov ss、ax'' mov sp、0x9000' –

+0

私はデバッガを使用しませんでしたが、jmpのときCODE_SEG:init_pmはシステムは何のエラーもなく停止しますが、bochsは保護モードへの切り替えについて通知しません。 –

答えて

3

TL; DR:32ビットモードで動作しているプロセッサのための命令を生成するFASMを取得するbits = 32

use32への変更を固定します。 セクション1.1.4出力フォーマットFASM Documentation状態:ソースファイルにはフォーマット指示がない場合、デフォルトで

は、フラットアセンブラは、単純にこのようフラットバイナリファイルを作成し、出力に生成された命令コードを置きます。 デフォルトことにより、16ビットコードを生成しますが、あなたは常に16ビットまたはUSE16またはUSE32ディレクティブを使用して32ビットモードにそれを回すことができます。

FASMによって受け入れられなかったFASMbits 32NASMコードを変換するときにbits = 32を使用し表示されます。 bits=32は、bitsという名前の定数値を32に設定します。FASMには、プロセッサが32ビットモードで使用する命令を生成するように指示しません。 bits = 32は間違いなく組み立てましたが、期待通りの出来ませんでした。あなたは16ビットの実モードで動作する32ビットのアドレスとオペランドを使用する命令ではなく、仕事の32ビットのアドレスとオペランドを使用する命令でinit_pm後にコードを生成するためにFASMに語ったuse32を使用していないことで

32ビット保護モードで動作します。


私はあなたのコードをテストすることはできませんが、私は私はあなたがやったポストコードと続いてきたかもしれないことを理解しようとしたときにこれらの観察をするつもりです。まず、これらの行をダンプしすべてBOCHSの:

[CPU0 ] 0x0000000000007d2f>> or dword ptr ds:[eax], eax : 0900 
[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting 

これは、アドレスの命令0x7d2f or dword ptr ds:[eax], eaxは(そのエンコーディングが0900である)に遭遇し、例外13(一般保護違反)が生成されたと述べています。

BOCHS状態ダンプで物事はあなたがプロテクトモードである提案する時があります。またjmp CODE_SEG:init_pmが正しく実行されたこと兆候がある

CPU is in protected mode (active) 

。これは、エラー時にBOCHSダンプされたCS:0008という意味で、のCSが値0008(= CODE_SEG)に設定されているという事実によって示唆されています。 DSセレクタは、JMPあなたがDATA_SEG(0×10)BUT ESに設定し、後SSセグメントセレクタが0x10のに設定されたことを考えると珍しい0です。これはすべてコードが実行されたと示唆していますが、何とか期待通りに実行されませんでした。私はあなたがそれは32ビットモードで実行されるCPUをターゲットにされるコードを生成するFASMを教えてくれない効果的に値32に定数を設定bits = 32を書いていたが実現。この時点で

。私は-b32オプションを使用してNDISASMと私のテストコードをダンプ

init_pm: 
    mov ax,DATA_SEG 
    mov ds,ax 
    mov ss,ax 
    mov es,ax 

    mov ebp, 0x90000 

(力:これを考慮して

は私が指示を取ると、アセンブラは16ビットモードのためにそれらをエンコードすることにしました32ビットのターゲットとして復号するNDISASM)、それはそれを復号化:誤った復号化が最初mov eax, 0xd88e0010をした

00000000 B810008ED8  mov eax,0xd88e0010 
00000005 8ED0    mov ss,eax 
00000007 8EC0    mov es,eax 
00000009 66BD0000   mov bp,0x0 
0000000D 0900    or [eax],eax 
0000000F 6689EC   mov sp,bp 

。これはなぜBOCHSダンプにEAX=d88e0010があるのか​​を説明します。 EAXの下位16ビットは、ESに移動しました。そのため、BOCHS と一致するES = 0x0010になります。同様のことがSSに設定されています。 BPは0に設定され、これはBOCHS出力BP:0000で確認されました。この命令は、障害やクラッシュが発生します。

0000000D 0900    or [eax],eax 

or [eax],eaxor ds:[eax],eaxと同じです。 [eax]は、DSへの暗黙の参照を持ちます。

0x0000000000007d2f>> or dword ptr ds:[eax], eax : 0900 

AHA、この異常な命令は(あなたがDWORD PTRを無視することができます)どこから来たことがある:BOCHS出力にこの命令を比較してください。誤ってデコードされた命令は、NULL(0x0000)記述子を指すDSを使用しようとします。これによりプロセッサの障害が発生し、その後のエラーはBOCHSと状態ダンプによって報告されます。


は、私はブートローダとカーネルをデバッグする場合は特にBOCHSが貴重であるで内部デバッガを使用して、コメントで述べたように。デバッガで一度に1つずつブートローダの命令を実行した場合は、FAR JMPinit_pmが期待どおりに動作していた可能性があります。予期せぬ命令が実行され、最終的にprocessor faultにつながったことが確認されました。

+0

ご返信遅れて申し訳ありませんが、感謝!!できます。現在エラーは表示されません。しかし別の問題が発生しました.Bochsは保護モードへの切り替えを何も出力せず、print32は何も印刷していません。何が問題なのかを教えてもらえますか?私はコードを編集し、print32.asmファイルを掲示しました。 –

+0

@AneeshSharmaあなたの新しい問題は新しい質問でなければならず、おそらくデバッガを使って解決するのですが、なぜプリントがうまくいかないのかについては、実際にビデオメモリをどこで更新するのかわかりません。 je print_string32_endの後に 'mov [edx]、ax'が見つからないようです。 –

+0

それは私の愚かな間違いでした。私はそれを追加しましたが、それはまだ動作しません。 –