現在、低レベルのプログラミング スキルを磨くために、x86 アセンバーをいじっています。現在、32 ビット プロテクト モードでのアドレッシング スキームに関する小さな問題に直面しています。
状況は次のとおりです。
CPU を保護モードに切り替え、コード内の対応するラベルにジャンプするプログラムを 0x7e0 にロードしました。
[...]
code to switch CPU in Protected Mode
[...]
jmp ProtectedMode
[...]
bits 32
ProtectedMode:
.halt:
hlt
jmp .halt
これまでのところ、これはまったく問題なく機能します。「jmp ProtectedMode」は、プリフェッチ キューをクリアするための明示的な far jump なしで機能します。このプログラムはオフセット 0 (最初は org 0) でロードされるため、コード セグメントが正しい場所を指すようになります。
私の現在の問題は、「ProtectedMode」ラベル内で、0x8000 にロードされている他のプログラムにジャンプしたいということです (これをメモリ ダンプで確認したところ、ロード機能は正しく機能し、プログラムは 0x8000 に正しくロードされました)。 .
CPU が RealMode ではなく ProtectedMode になったため、アドレス指定スキーマが異なります。ProtectedMode は記述子セレクターを使用して記述子テーブルのベース アドレスと制限を検索し、指定されたオフセットを追加して物理アドレスを取得します (私が理解しているように)。そのため、ProtectedMode に入る前に GDT をインストールする必要がありました。
私は次のようになっています:
%ifndef __GDT_INC_INCLUDED__
%define __GDT_INC_INCLUDED__
;*********************************
;* Global Descriptor Table (GDT) *
;*********************************
NULL_DESC:
dd 0 ; null descriptor
dd 0
CODE_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
DATA_DESC:
dw 0xFFFF ; data descriptor
dw 0 ; limit low
db 0 ; base low
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
gdtr:
Limit dw 24 ; length of GDT
Base dd NULL_DESC ; base of GDT
%endif ;__GDT_INC_INCLUDED__
経由で GDT レジスタにロードされます。
lgdt [gdtr]
これまで理解できなかったのは、GDT を使用して ProtectedMode の物理アドレス 0x8000 にジャンプするにはどうすればよいかということです。
私の最初の考えは、0x7e00 (現在のプログラムがロードされている場合) を指すコード記述子 (CODE_DESC) を選択し、0x8000 (512 バイト) に到達するために必要なオフセットを使用して、ジャンプ命令を作成することでした:
jmp CODE_DESC:0x200
しかし、これはうまくいきません。
jmp 0x7e0:0x200
どちらも機能しません...
ここで何が欠けているのか分かりますか? 32 ビット ProtectedMode アドレッシング スキームと GDT の使用法に不可欠な要素を理解していなかったのかもしれません。
[編集] 完全なコード:
bits 16
org 0 ; loaded with offset 0000 (phys addr: 0x7e00)
jmp Start
Start:
xor ax, ax
mov ax, cs
mov ds, ax ; update data segment
cli ; clear interrupts
lgdt [gdtr] ; load GDT from GDTR (see gdt_32.inc)
call OpenA20Gate ; open the A20 gate
call EnablePMode ; jumps to ProtectedMode
;******************
;* Opens A20 Gate *
;******************
OpenA20Gate:
in al, 0x93 ; switch A20 gate via fast A20 port 92
or al, 2 ; set A20 Gate bit 1
and al, ~1 ; clear INIT_NOW bit
out 0x92, al
ret
;**************************
;* Enables Protected Mode *
;**************************
EnablePMode:
mov eax, cr0
or eax, 1
mov cr0, eax
jmp ProtectedMode ; this works (jumps to label and halts)
;jmp (CODE_DESC-NULL_DESC):ProtectedMode ; => does not work
;jmp 08h:ProtectedMode , => does not work
;***************
;* data fields *
;* &includes *
;***************
%include "gdt_32.inc"
;******************
;* Protected Mode *
;******************
bits 32
ProtectedMode:
;here I want to jump to physical addr 0x8000 (elf64 asm program)
.halt:
hlt
jmp .halt