0171-建立核心可執行檔案

波尔發表於2024-07-13

環境

  • 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。

附錄

相關文章