5日目 その2

今回は変数の値の表示です。


OS自作本で使っているコンパイラ(GO)にはおまけでsprintfがついてますが、gccにはそんなものはない(はず)です。で、どうするかというとGOからパクってきます。(オープンソース万歳ですな)
ソースは以下のURLにあります。


http://k.hideyosi.com/go_0020s.lzh


これを展開するとgolibcというディレクトリがあり、この中にsprintfのソースもあります。
この中のファイルを全部コンパイルしてリンクしてやればいいのですが、それだと芸がないしなによりバイナリサイズが無駄に大きくなってしまうので、ここではスタティックライブラリを作ってそいつをリンクしてやることにします。



以下golibc用のMakefileです。

TARGET     = libgolibc.a
STACKSIZE  =
MALLOCSIZE =
MMAREA     =
OBJS       = abs.o atof.o atoi.o errno.o frexp.o ldexp.o \
	memchr.o memcmp.o memmove.o memset.o qsort.o rand.o \
	sprintf.o strcat.o strcmp.o strcpy.o strcspn.o strdup.o \
	strlen.o strncat.o strncmp.o strncpy.o strpbrk.o strrchr.o \
	strspn.o strstr.o strtol.o strtoul.o strtoul0.o vsprintf.o

CC = gcc
CFLAGS = -I. -fno-common -Wall -O2 -c \
         -finhibit-size-directive -fno-ident \
         -fomit-frame-pointer -fcall-used-ebx
AR = ar

ALL : ${OBJS}
	${AR} rv ${TARGET} ${OBJS}
	ranlib ${TARGET}

.c.o:
	${CC} ${CFLAGS} $<

clean :
	rm -f *.o ${TARGET}

できたlibgolibc.aをリンクするルールは以下のとおり。

${BOOTPACK}: ${OBJS} bootpack.ls golibc/libgolibc.a
	ld -T bootpack.ls -o $@ ${OBJS} -static -L./golibc -lgolibc \
	-Map ${BOOTPACK}.map --cref

これでsprintfが使えるようになりました。
リンク時に作られるbootpack.mapをみるとたしかにリンクされているのがわかります。

 .text          0x0000000000000510       0x20 ./golibc/libgolibc.a(sprintf.o)
                0x0000000000000510                sprintf
 .text          0x0000000000000530      0x42b ./golibc/libgolibc.a(vsprintf.o)
                0x0000000000000530                vsprintf
 *fill*         0x000000000000095b        0x5 00
 .text          0x0000000000000960       0x29 ./golibc/libgolibc.a(strlen.o)
                0x0000000000000960                strlen
 *fill*         0x0000000000000989        0x7 00
 .text          0x0000000000000990      0x150 ./golibc/libgolibc.a(strtoul0.o)
                0x00000000000009f0                strtoul0

おまけとしてトップディレクトリのMakefileも載せときます。

CC = gcc
CFLAGS = -fno-common -Wall -O2 -c \
         -finhibit-size-directive -fno-ident \
         -fomit-frame-pointer -fcall-used-ebx

TARGET = hello
IPL = ipl
ASMHEAD = asmhead
BOOTPACK = bootpack
OBJS = crt.o bootpack.o asmfunc.o hankaku.o
SUBDIRS = golibc

all:
	$(MAKE) $(AM_MAKEFLAGS) all-recursive
	$(MAKE) $(AM_MAKEFLAGS) ${TARGET}.bin

all-recursive:
	list='$(SUBDIRS)'; for subdir in $$list; do \
	echo "Making in $$subdir"; \
	cd $$subdir && $(MAKE) $(AM_MAKEFLAGS); \
	done;

clean-recursive:
	list='$(SUBDIRS)'; for subdir in $$list; do \
	echo "Making clean in $$subdir"; \
	cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) clean; \
	done;

${TARGET}.bin: ${IPL} ${ASMHEAD} ${BOOTPACK}
	dd if=/dev/zero of=$@ bs=512 count=2880 &> /dev/null
	dd if=${IPL} of=$@ conv=notrunc &> /dev/null
	dd if=${ASMHEAD} of=$@ conv=notrunc seek=1 &> /dev/null
	dd if=${BOOTPACK} of=$@ conv=notrunc seek=2 &> /dev/null

${IPL}: ipl.o ipl.ls
	ld -T ipl.ls -o $@ ipl.o \
	-Map ${IPL}.map --cref

${ASMHEAD}: asmhead.o asmhead.ls
	ld -T asmhead.ls -o $@ asmhead.o \
	-Map ${ASMHEAD}.map --cref

${BOOTPACK}: ${OBJS} bootpack.ls golibc/libgolibc.a
	ld -T bootpack.ls -o $@ ${OBJS} -static -L./golibc -lgolibc \
	-Map ${BOOTPACK}.map --cref

hankaku.c: hankaku.txt
	ruby hankaku.rb $< > $@

%.o: %.S Makefile
	${CC} ${CFLAGS} $<

%.o: %.c Makefile
	${CC} ${CFLAGS} $<

clean:
	$(MAKE) $(AM_MAKEFLAGS) all-recursive
	rm -f *.o *.map ${IPL} ${ASMHEAD} ${BOOTPACK} ${TARGET}.bin

.PHONY: all all-recursive clean clean-recursive