环境
- 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。