0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

x86 16ビットモードから32ビットへ移行するアセンブリコード

Posted at

目的

x86系のCPUは、電源を入れた時は16ビットモードで動いています。
今回は32ビットモードへ切り替える実験をします。
切り替えたかどうか、見た目で分からないので32ビットのEBXに入れた文字をVRAMへ書き込み、表示されたことを以て32ビットに切り替わっていることの証明とします。

32ビットモードへ入る時にやること

1.GDTの読み込み
2.CR0レジスタの0ビット目を1にする
3.jmp命令を実行し16ビットモードのままのCS:IPを更新する。

実装

boot.asm
[org 0x7C00]
bits 16

start:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00
    sti

    ; --- INT 13h CHS 読み込み ---
    mov ah, 0x02         ; BIOS: Read Sectors
    mov al, 1            ; 読み込むセクタ数 (1)
    mov ch, 0            ; シリンダ = 0
    mov dh, 0            ; ヘッド = 0
    mov cl, 2            ; セクタ = 2 (ブートローダの次)
    mov dl, 0x80            ; ドライブ番号=HDD
    mov bx, 0x7E00       ; ES:BX = 読み込み先
    int 0x13
    jc disk_error

    jmp 0x0000:0x7E00    ; 読み込んだコードへジャンプ

disk_error:
    hlt
    jmp disk_error

times 510-($-$$) db 0
dw 0xAA55
test.asm
[org 0x7E00]
bits 16

start:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00
    
    mov ax, 0x0003
    int 0x10 

    ; VGAリアルモード表示
    mov ax, 0xB800
    mov es, ax
    mov word [es:0], 0x0F41   ; 'A'
    mov word [es:2], 0x0F42   ; 'B'

    ; GDTロード
    lgdt [gdt_descriptor]

    ; プロテクトモード有効化
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; 32ビットコードへジャンプ
    jmp 0x08:pm_start

; -----------------------------
gdt_start:
    dq 0x0000000000000000            ; NULL

gdt_code:
    dw 0xFFFF                        ; limit 0-15
    dw 0x0000                        ; base 0-15
    db 0x00                          ; base 16-23
    db 0x9A                          ; code segment
    db 0xCF                          ; flags
    db 0x00                          ; base 24-31

gdt_data:
    dw 0xFFFF
    dw 0x0000
    db 0x00
    db 0x92                          ; data segment
    db 0xCF
    db 0x00
gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

; -----------------------------
[bits 32]
pm_start:
    ; データセグメント設定(フラット)
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov esp, 0x9FC00
    
    mov ebx, 0x32334B4F   ; 'O','K','3','2'
    mov edi, 0xB8000
    mov ecx, 4

display_loop:
    mov al, bl        ; 下位バイトを取り出す
    mov ah, 0x0F      ; 属性固定
    mov [edi], ax
    add edi, 2
    shr ebx, 8        ; 次の文字を下位に
    loop display_loop


.hlt_loop:
    hlt
    jmp .hlt_loop

; -----------------------------
times 512-($-$$) db 0

動作確認

nasm -f bin boot.asm -o boot.bin
nasm -f bin test.asm -o test.bin
cat boot.bin test.bin > disk.img

ThinkPad X280

BIOSの設定がUEFIではなく従来のBIOS起動となっていることを確認します。

lsblk
sudo dd if=disk.img of=/dev/sdb bs=512 count=2 conv=notrunc

7c1a4a15634058.jpg
846321c5409f38.jpg

※thinkpadでは起動出来ましたが、手持ちのゲーミングノートMSI(MS-16R4)は起動出来ませんでした。
OS無しのコードを書くとthinkpadでは大抵動きますが、MSIでは殆ど起動すら出来ません。
低レイヤの好きな方はthinkpadをご購入されることをお薦めします。

QEMU

qemu-system-i386 -hda disk.img

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?