2012-02-06 5 views
5

intel x86でプロテクトモードに切り替えることを試みています。プロテクトモードに切り替えた後に「コール」する

私は、lgdtと私のGDTをロード1にCR0のPフラグを設定し、すべてのセグメントセレクタが、私は、関数呼び出しから戻ったとき、私は他の関数を呼び出すことはできませんか、私はこのエラー

を取得しましたここで
qemu: fatal: Trying to execute code outside RAM or ROM at 0xfeeb7c5b 

は私のswitch_to_pmode機能である:

gdtr: 
.short  23 // limit 
gdtr_base: 
.long  0 // base 

switch_to_pmode: 
    movl $null_segment, %eax  // Address of the first byte of the GDT 
    movl %eax, gdtr_base 

    cli    // disable interrupts 

    lgdt (gdtr) 

    movl %cr0, %eax 
    or $0x1, %eax 
    movl %eax, %cr0   // Set the PE flag 

    push $0x8 
    push $reload_segments 
    lret 

reload_segments: 
    movl $0x10, %eax 
    movl %eax, %ds 
    movl %eax, %ss 
    movl %eax, %es 
    movl %eax, %fs 
    movl %eax, %gs 

    ret 

foo: 
    ret 

そして、私の呼び出し

_start: 
    call switch_to_pmode 
    call foo // <----- Ouch! 

感謝

答えて

3

保護モードスイッチに続くコードを.code32(またはnasmのuse32)ディレクティブで32ビットコードとして変換する必要があります。

保護モードルーチンの後の戻りアドレスは、もは​​や有効ではありません。あなたは本当にその後何にも戻ることはできません。代わりにespを何か有用なものに設定してください。 PEを設定またはクリアしますCR0へ

+0

ありがとうございました! .code32が機能します! – marmottus

3

動きはすぐには、PCを再ロードするためにこれまでのジャンプが続かなければならない、とあなたは%espだけでなく、すべてのセグメントレジスタをリロードする必要があります。 のすべてを実行してからにスタックをタッチするか、割り込みを有効にする必要があります。また、復帰アドレスがリアルモードのアドレスであるため、に復帰することは不可能です(リアルモードスタックを無効にする前にリターンアドレスをポップしても)。

lretを使用してPCをリロードし、同時に割り込みを再び有効にしようとしているように見えますが、スタックポインタが無効であるため、割り込みが機能しません。正しいコードは次のようになります:

switch_to_pmode: 
    # ... what you have ... 

    movl %eax, %cr0 
.code32 
    ljmpl reload_segments 

reload_segments: 
    # ... what you have ... 
    movl $pm_stack, %esp 
    sti # perhaps 

    # and then just go on with your startup code here 
    call foo 

あなたは詳細に説明し、インテルのsystem programming guide、特に第9章(マシンの初期化)、特にセクション9.9は、保護されたモードスイッチを行う方法をお読みください。

+0

AFAIK far jumpが実行されない限り、CPUはまだリアルモードで動作します。私は 'プッシュ$ 8;プッシュreload_segments;遠隔ジャンプを実行する創造的な方法として「retl」を使用する。しかし、あなたが記述する方法は標準的な方法であり、それは信頼できる方法である。 – hirschhornsalz

+1

これは創造的ですが、動作することは保証されていません - アーキテクチャのマニュアルは非常に明確です: "MOV CR0命令の直後に遠いJMPまたは遠方のCALL命令を実行します。 [これらの指示]。 (「インテル®64およびIA-32アーキテクチャー・ソフトウェア開発者マニュアル第3巻:システム・プログラミング・ガイド」(http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures) -software-developer-system-programming-manual-325384.pdf)、セクション9.9) – zwol

関連する問題