x86 アセンブリを学んでおり、NASM でおもちゃのオペレーティング システムを作成しようとしていますが、いくつかのことがわかりません。
カーネルを正常に起動するブートローダーを作成しました。
- カーネル ファイルを含むディスケットから 14 セクタをロードします。
- というラベルの付いたこれらのセクターでファイルを検索します
kernel.feo
。 - そのファイルをオフセットのメモリにロードします
0x2000
。 - far jump を使用してカーネルを実行します
jmp 0x2000:0x0000
。
したがって0x2000:0
、メモリ内にカーネルコードがあります。CS
ファージャンプを使用しているため、適切に設定されている可能性があります。このカーネル コードでは、32 ビット プロテクト モードに入りたいのですが、GDT がどのように機能しているかわかりません。以下のコードを仮想マシン(QEMU)
で実行すると、何も実行されません。
32 ビット プロテクト モードに入るのを手伝ってください!
とはいえ、次の問題があります。
0x7c00:0
が原因でコードが にロードされていると想定していますがorg 0
、そうではない可能性があります。保証されるのは物理アドレスだけです。CS
適切に設定されるように、エントリ ポイントへのファー ジャンプを使用する必要があります。- 何らかの理由で、コードがデータをまったく検出しないように設定
DS
しています。matchに0x2000
設定するか、どこでもオーバーライドを使用する必要があります (推奨されません)。DS
CS
CS
- プロテクト モードのコードはゼロから始まるセグメントを前提と
org 0x7c00
しています。org 0x7c00
および セグメントに切り替える必要があり0
ます。- VGA テキスト モード セグメントは
0xb8000
not0xb80000
(ゼロを 1 つ引いた値) です。0x55 0xaa
ブート セクタの最後にブート署名バイトがありません。
コードで次のことを修正しました。
[org 0x0]
は に修正され[org 0x2000]
、セグメントは に設定され0
ます。DS
0
の代わりに に修正されたので、 ;0x2000
と一致するようになりました。CS
- VGA テキスト モード セグメントは に修正されました
0xb8000
。
しかし、コードはこれらの修正では機能しません。2 つの文字列を出力するはずですが、何もしません!
このカーネル コードは0x55 0xAA
、ブート セクターではないため、ブート署名で終わらないように注意してください。
修正されたカーネル コードは次のとおりです (動作していません)。
[bits 16]
[org 0x2000]
jmp 0:kernel_start
gdt_start:
gdt_null:
dd 0x0
dd 0x0
gdt_code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
print:
mov ah, 14
mov bh, 0
lodsb
cmp al, 0
je .done
int 0x10
jmp print
.done:
ret
uzenet_real db 'uzenet16', 0
uzenet_prot db 'uzenet32', 0
kernel_start:
mov ax, 0
mov ss, ax
mov sp, 0xFFFC
mov ax, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov si, uzenet_real
call print
cli
lgdt[gdt_descriptor]
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:b32
[bits 32]
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
print32:
pusha
mov edx, VIDEO_MEMORY
.loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je .done
mov [edx], ax
add ebx, 1
add edx, 2
jmp .loop
.done:
popa
ret
b32:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x90000
mov esp, ebp
mov ebx, uzenet_prot
call print32
jmp $