gasとcでHello,worldしてみる
gasを使ってプログラムを書いてみよう。
まずは伝統的にhello,worldからはじめる。
アセンブラで記述しなければならないのはセグメントレジスタの設定のみで、後はCで記述できる。
GAS
ここではセグメントレジスタを設定したあとhelloへジャンプしている:
crt.S
#define INIT_SEG 0x07c0 // boot loaded here #define INIT_ESP 0xfff0 // stack starts here .code16gcc .intel_syntax noprefix .text .extern hello // start C function .global _start _start: jmp INIT_SEG, offset reentry reentry: cli mov ax, cs mov ds, ax mov es, ax mov ss, ax mov esp,INIT_ESP sti jmp hello
C
ここではBIOSを使ってHello,wordlを表示させてみる:
hello.c
asm(".code16gcc"); /* 16bit-realmode */ asm(".intel_syntax noprefix"); /* I hate AT&T-style */ void hello() { char *msg = "hello,world"; while(*msg) asm volatile("int 0x10" : : "a" (0x0e00 | (*msg++ & 0xff)), "b" (15)); for(;;) ; }
リンカスクリプト
リンカスクリプトは非常にシンプルで、ただcrt.oとipl.oをくっつける。さらに510番地にブートシグネチャを書き込んでいる:
simple.ls
OUTPUT_FORMAT("binary"); IPLBASE = 0x0000; SECTIONS { . = IPLBASE; .ipl : { crt.o ipl.o } . = IPLBASE + 510; .sign : {SHORT(0xAA55)} }
コンパイル
gcc crt.S -c gcc hello.c -c -masm=intel ld -T=simple.ls crt.o hello.o -o boot.bin
表示されたかな
うまくいけばhello,worldが表示されていると思う。
次回からはプログラムをもう少し拡張しブートローダーを作ってみる