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