概要
wslで、kernel.elfのコンパイル、やってみた。
cで、書いてみた。
参考にしたページ
手順
cで、kernelを書く。
- 画面クリアして、「Hello world」を表示。
kernel.h
#ifndef KERNEL_H
#define KERNEL_H
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#define VGA_ADDRESS 0xB8000
#define BUFSIZE 2200
uint16* vga_buffer;
#define NULL 0
enum vga_color {
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
GREY,
DARK_GREY,
BRIGHT_BLUE,
BRIGHT_GREEN,
BRIGHT_CYAN,
BRIGHT_RED,
BRIGHT_MAGENTA,
YELLOW,
WHITE,
};
#endif
kernel.c
#include "kernel.h"
uint16 vga_entry(unsigned char ch, uint8 fore_color, uint8 back_color) {
uint16 ax = 0;
uint8 ah = 0, al = 0;
ah = back_color;
ah <<= 4;
ah |= fore_color;
ax = ah;
ax <<= 8;
al = ch;
ax |= al;
return ax;
}
void clear_vga_buffer(uint16 ** buffer, uint8 fore_color, uint8 back_color) {
uint32 i;
for(i = 0; i < BUFSIZE; i++)
{
(*buffer)[i] = vga_entry(NULL, fore_color, back_color);
}
}
void init_vga(uint8 fore_color, uint8 back_color) {
vga_buffer = (uint16*)VGA_ADDRESS;
clear_vga_buffer(&vga_buffer, fore_color, back_color);
}
void kernel_entry() {
init_vga(WHITE, BLACK);
vga_buffer[0] = vga_entry('H', WHITE, BLACK);
vga_buffer[1] = vga_entry('e', WHITE, BLACK);
vga_buffer[2] = vga_entry('l', WHITE, BLACK);
vga_buffer[3] = vga_entry('l', WHITE, BLACK);
vga_buffer[4] = vga_entry('o', WHITE, BLACK);
vga_buffer[5] = vga_entry(' ', WHITE, BLACK);
vga_buffer[6] = vga_entry('W', WHITE, BLACK);
vga_buffer[7] = vga_entry('o', WHITE, BLACK);
vga_buffer[8] = vga_entry('r', WHITE, BLACK);
vga_buffer[9] = vga_entry('l', WHITE, BLACK);
vga_buffer[10] = vga_entry('d', WHITE, BLACK);
}
アセンブラを書く。
gas(nasmじゃない)
grubで、起動できるように、multiboot書く。
boot.S
.set MAGIC, 0x1BADB002
.set FLAGS, 0
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
stackBottom:
.skip 1024
stackTop:
.section .text
.global _start
.type _start, @function
_start:
mov $stackTop, %esp
call kernel_entry
cli
hltLoop:
hlt
jmp hltLoop
.size _start, . - _start
リンカーを書く。
linker.ld
ENTRY(_start)
SECTIONS
{
. = 1M;
.text BLOCK(4K) : ALIGN(4K) {
*(.multiboot)
*(.text)
}
.rodata BLOCK(4K) : ALIGN(4K) {
*(.rodata)
}
.data BLOCK(4K) : ALIGN(4K) {
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K) {
*(COMMON)
*(.bss)
}
}
Makefileを書く。
- elfを作る。
Makefile
all: kernel1.elf
kernel1.elf: kernel.o boot.o
ld -m elf_i386 -T linker.ld kernel.o boot.o -o kernel1.elf -nostdlib
kernel.o: kernel.c
gcc -m32 -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
boot.o: boot.S
as --32 boot.S -o boot.o
clean:
$(rm) boot.o kernel.o kernel1.elf
makeする。
- kernel1.elfが、できる。
確認する。
$ readelf -a kernel1.elf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x100511
Start of program headers: 52 (bytes into file)
Start of section headers: 6240 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 40 (bytes)
Number of section headers: 10
Section header string table index: 9
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00100000 001000 00051f 00 AX 0 0 4096
[ 2] .text.__x86.get_p PROGBITS 0010051f 00151f 000004 00 AX 0 0 1
[ 3] .eh_frame PROGBITS 00100524 001524 00007c 00 A 0 0 4
[ 4] .got.plt PROGBITS 001005a0 0015a0 00000c 04 WA 0 0 4
[ 5] .bss NOBITS 00101000 002000 000004 00 WA 0 0 4096
[ 6] .comment PROGBITS 00000000 0015ac 000029 01 MS 0 0 1
[ 7] .symtab SYMTAB 00000000 0015d8 000180 10 8 17 4
[ 8] .strtab STRTAB 00000000 001758 0000a7 00 0 0 1
[ 9] .shstrtab STRTAB 00000000 0017ff 00005e 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00100000 0x00100000 0x005a0 0x005a0 R E 0x1000
LOAD 0x0015a0 0x001005a0 0x00101000 0x0000c 0x0000c RW 0x1000
LOAD 0x002000 0x00101000 0x00102000 0x00000 0x00004 RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Section to Segment mapping:
Segment Sections...
00 .text .text.__x86.get_pc_thunk.ax .eh_frame
01 .got.plt
02 .bss
03
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 24 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00100000 0 SECTION LOCAL DEFAULT 1
2: 0010051f 0 SECTION LOCAL DEFAULT 2
3: 00100524 0 SECTION LOCAL DEFAULT 3
4: 001005a0 0 SECTION LOCAL DEFAULT 4
5: 00101000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 6
7: 00000000 0 FILE LOCAL DEFAULT ABS boot.o
8: 1badb002 0 NOTYPE LOCAL DEFAULT ABS MAGIC
9: 00000000 0 NOTYPE LOCAL DEFAULT ABS FLAGS
10: e4524ffe 0 NOTYPE LOCAL DEFAULT ABS CHECKSUM
11: 0010000c 0 NOTYPE LOCAL DEFAULT 1 stackBottom
12: 0010040c 0 NOTYPE LOCAL DEFAULT 1 stackTop
13: 0010051c 0 NOTYPE LOCAL DEFAULT 1 hltLoop
14: 00000000 0 FILE LOCAL DEFAULT ABS kernel.c
15: 00000000 0 FILE LOCAL DEFAULT ABS
16: 001005a0 0 OBJECT LOCAL DEFAULT 4 _GLOBAL_OFFSET_TABLE_
17: 00100460 63 FUNC GLOBAL DEFAULT 1 init_vga
18: 00100430 44 FUNC GLOBAL DEFAULT 1 clear_vga_buffer
19: 00101000 4 OBJECT GLOBAL DEFAULT 5 vga_buffer
20: 0010051f 0 FUNC GLOBAL HIDDEN 2 __x86.get_pc_thunk.ax
21: 001004a0 113 FUNC GLOBAL DEFAULT 1 kernel_entry
22: 00100511 14 FUNC GLOBAL DEFAULT 1 _start
23: 00100410 23 FUNC GLOBAL DEFAULT 1 vga_entry
No version information found in this file.
以上。