文字出力の実装が終わりましたので、
32bitモードに移行することにしましょう。
32bitモードへの移行は次の流れで行います。
mov al, 0Dh out 70h, al in al, 80h in al, 71h
mov ax, 2401h stc int 15h jnc boot_unmask_A20line_ok call boot_kbc_wait mov al, 0D1h out 64h, al call boot_kbc_wait mov al, 0DFh out 60h, al call boot_kbc_wait boot_unmask_A20line_ok:
boot_kbc_wait: in al, 64h test al, 02h jnz boot_kbc_wait ret
| オフセット | サイズ | 機能 |
| +00h | 2-byte | リミットのbit 15-0です。 |
| +02h | 2-byte | ベースアドレスのbit 15-0です。 |
| +04h | 1-byte | ベースアドレスのbit 23-16です。 |
| +05h | 1-byte | descriptorの種類とフラグです。 bit 7(80h)を設定すると、このdescriptorが存在することを示します。 クリアするとアクセス時に例外が発生します。 bit 5-6(00h,20h,40h,60h)はdescriptorの特権レベル(DPL)を表します。 bit 4-0はdescriptorの種類を表します。特に、 bit 4(10h)はdescriptorがコードやデータのとき設定され、 システム用のときクリアされます。 bit 4-0 の例を示します。 |
| +06h | 1-byte |
下位4bitはリミットのbit 19-16です。 上位4bitはフラグです。 bit 7(80h)を設定すると、リミットが4096倍されます。 bit 6(40h)を設定すると、コードやスタックのデフォルトサイズが32bitになります。 |
| +07h | 1-byte | ベースアドレスのbit 31-24です。 |
align 8,db 0 pm32_gdt_begin: ; 00h: null selector. dw 0 ; seg limit = 0Fh dw 0 ; seg base 15:0 = 0 dw 0 ; seg base 23:16 = 0h, type = 0h db 0 ; seglimit 19:16 and flags db 0 ; segbase 31:24 ; 08h: 32-bit code selector. base=0, limit=4G. dw 0FFFFh ; seg limit = 0FFFFh dw 0000h ; seg base 15:0 = 0000h dw 9A00h ; seg base 23:16 = 00h, type = 9Ah(code) db 0CFh ; seglimit 19:16 and flags db 0h ; segbase 31:24 ; 10h: 32-bit data selector. base=0, limit=4G. dw 0FFFFh ; seg limit = 0FFFFh dw 0000h ; seg base 15:0 = 0000h dw 9200h ; seg base 23:16 = 00h, type = 92h(data) db 0CFh ; seglimit 19:16 and flags db 0h ; segbase 31:24 pm32_gdt_end:
pm32_gdtr_top: dw pm32_gdt_end - pm32_gdt_begin - 1 ; limit (=length - 1) dd (0060h << 4) + pm32_gdt_begin ; linear address
lgdt [cs:pm32_gdtr_top] ; load GDTR. mov eax, CR0 or al, 1 mov CR0, eax db 0EAh ; far jmp dw (0060h<<4) + real_switch_to_pm32_entry ; entry point (offset) dw 0008h ; entry point (selector) BITS 32 real_switch_to_pm32_entry: mov ax, 0010h mov ds, ax mov es, ax mov ss, ax mov esp, 110000h xor eax, eax mov fs, ax mov gs, ax