環境
- Time 2022-11-11
- WSL-Ubuntu 22.04
- QEMU 6.2.0
- NASM 2.15.05
前言
說明
參考:https://os.phil-opp.com/multiboot-kernel/
目標
編寫一個可以載入執行的檔案。
啟動程式碼
global start
section .text
bits 32
start:
; print `OK` to screen
mov dword [0xb8000], 0x2f4b2f4f
hlt
start 是啟動入口,.text 表示是程式碼段。
bits 32 指定了編譯成 32 位的機器碼,因為需要在 32 位保護模式下執行。
0xb8000 是視訊記憶體地址,輸出使用。
hlt 是 CPU 停機指令。
編譯和反編譯
root@jiangbo12490:~/git/game# nasm boot.asm
root@jiangbo12490:~/git/game# hexdump -x boot
0000000 05c7 8000 000b 2f4f 2f4b 00f4
000000b
root@jiangbo12490:~/git/game# ndisasm -b 32 boot
00000000 C70500800B004F2F mov dword [dword 0xb8000],0x2f4b2f4f
-4B2F
0000000A F4 hlt
建立 ELF 檔案
ELF 主要是 linux 系統下的一種檔案格式。
nasm 預設輸出二進位制檔案,需要 ELF 檔案,需要增加引數 -f 指定,得到兩個 .o 檔案(物件檔案)。
root@jiangbo12490:~/git/game# nasm -f elf64 main.asm
root@jiangbo12490:~/git/game# nasm -f elf64 boot.asm
root@jiangbo12490:~/git/game#
連結物件檔案
自定義連結指令碼
ENTRY(start)
SECTIONS {
. = 1M;
.boot :
{
/* ensure that the multiboot header is at the beginning */
*(.multiboot_header)
}
.text :
{
*(.text)
}
}
- start 指定的程式入口。
- . = 1M 指定了程式需要被載入到哪個地址上。
- .boot 放到最開始,後面是 .text 段。
- multiboot_header 放到最前面。
連結
root@jiangbo12490:~/git/game# ld -n -o kernel.bin -T linker.ld main.o boot.o
root@jiangbo12490:~/git/game# ld -v
GNU ld (GNU Binutils for Ubuntu) 2.38
-n 不可以省略,關閉對齊。
檢視 section 資訊
root@jiangbo12490:~/git/game# objdump -h kernel.bin
kernel.bin: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 00000018 0000000000100000 0000000000100000 00000080 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000000b 0000000000100020 0000000000100020 000000a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
總結
建立了一個核心可執行程式 kernel.bin。