Hatena::ブログ(Diary)

Mafice’s Blog

2011 04/03

Longモードへの移行

エミュレータqemu-system-x86_64で。普通のqemuで実行すると、64bitのコードをきちんと実行できないかもしれません。


ロングモードではプロテクトモードでは必須でなかったページングが必要となり、

移行する前にこの様にページテーブルを作っておかないといけません。


cld
mov  si,  0xd100 ;このアドレスは適当


;レベル4・ページマップ・テーブルを設定
mov  di,   0xd000
mov  ax,   0xe00f   ;Present, Writable, User

; mov [edi], eax と同じ
mov  [si], ax
mov  cx,   4
rep  movsb




;ページディレクトリ・ポインタ・テーブルを設定
mov  di,   0xe000
mov  ax,   0xf00f   ;Present, Writable, User
mov  [di], ax

; mov [edi], eax と同じ
mov  [si], ax
mov  cx,   4
rep  movsb




;ページディレクトリを設定
setPTE:
mov  di,    0xf000
mov  ax,    0x018f     ;Present, Writable, User, Page size:2MB
mov  [di],  ax

; mov [edi], eax と同じ
mov  [si], ax
mov  cx,   4
rep  movsb

次にPAEとPGEを有効化。

mov  eax, cr4
or   eax, 0xa0
mov  cr4, eax

CR3にレベル4・ページマップ・テーブルのアドレスを指定

mov  eax, 0xd000
mov  cr3, eax

その次にロングモードを有効化。ここはよくわかんないです…。

mov   ecx, 0xc0000080
rdmsr
or    eax, 0x0100
wrmsr

プロテクトモードに入る。とはいってもすぐにLongモードに移行します。

mov     eax, cr0
or      eax, 0x80000001
mov     cr0, eax


;GDTを読み込む
loadGDT:
lgdt    [GDTR]


;0x8200に飛ぶ
jmp dword 8:0x8200



align 8

GDTR:
dw   GDT_END - GDT - 1
dq   GDT+0x8000
align 8


GDT:
;NULLディスクリプタ
dw 0
dw 0
db 0
db 0
db 0
db 0

;コードディスクリプタ
dw 0
dw 0
db 0
db 0x98
db 0x20
db 0

;データディスクリプタ
dw 0
dw 0
db 0
db 0x90
db 0
db 0

GDT_END:

0x8200からはLongモードになってます。

[bits 64]
[org   0]

;なんか寂しいから一文字表示
mov edi, 0xb8000
mov byte [edi], 0x41
mov edi, 0xb8001
mov byte [edi], 0x41

mov rax, 0x123456789abcdef

hlt:
hlt
jmp hlt

そしてRAXの中身を見てみると、0x123456789abcdefになってるはずです。


Entering Long Mode Directly - OSDev Wiki

x86_64のLongモードをやってみる - Just Do Live

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Mafice/20110403/1301811262
リンク元