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が表示されていると思う。
次回からはプログラムをもう少し拡張しブートローダーを作ってみる