保護モードに切り替えた後の「呼び出し」

私はIntel x86のプロテクトモードに切り替えようとしています。

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

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!

ありがとうございました

5

2 答え

PEを設定またはクリアするCR0への移動は、PCをリロードするために遠くにジャンプする直ちにする必要があります。そして、%esp とすべてのセグメントレジスタ。スタックをタッチするか、割り込みを有効にする前に、すべてを実行する必要があります。また、リターンアドレスがリアルモードのアドレスなので、リアルモードスタックを無効にする前にリターンアドレスをポップしても、この操作から返すことは不可能です(drhirsch氏)。

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

インテルのシステムプログラミングガイド、特に第9章(マシンの初期化)、特にセクション9.9、プロテクションモードの切り替え方法について詳しく説明しています。

3
追加された
"MOV CR0命令のすぐ後に、far JMPまたはfar CALL命令を実行してください... 他の命令が存在する場合、ランダムな障害が発生する可能性がありますを入力してください。 (強調する)(インテル®64およびIA-32アーキテクチャー・ソフトウェア開発者マニュアル第3巻:システム・プログラミング・ガイド、セクション9.9)
追加された 著者 zwol,
AFAIK遠方ジャンプが実行されていない限り、CPUはまだリアルモードで動作します。私は push $ 8;を読んだ。プッシュreload_segments; retl を遠くのジャンプを実行する独創的な方法として使用します。しかし、あなたが記述する方法は標準的な方法であり、それは信頼できる方法である。
追加された 著者 hirschhornsalz,

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

さらに、プロテクトモードルーチンの後の戻りアドレスはもはや有効ではありません。あなたは本当にその後何にも戻ることはできません。代わりにespを何か有用なものに設定してください。

3
追加された
ありがとうございました! .code32が機能します!
追加された 著者 marmottus,