C与汇编合作编程+Makefile
这周主要学习了保护模式下操作系统的加载与运行,但还没有完全学完。其中有个知识点是汇编语言与C语言合作实现一段程序。大概流程是这样:
(图来自《Orange'S:一个操作系统的实现》)
在Linux上实现,具体实现大致是:
①在写.asm程序的时候使用“extern”表示使用的函数来自外部文件,使用“global”表示函数可以被外部使用。C语言不需要特殊说明,按语法写即可,函数间采用栈传递参数,后面的参数先入栈。
②编译(compile),各自生成目标文件.o文件,汇编用nasm,C用gcc,此时的.o文件已经是机器语言文件了。
③链接(link),采用nasm,生成.bin文件。本质上是根据函数名将函数相互链接起来,因此一定不要重名!
④ld指令可以指定程序在内存中的位置:ld –s –Ttext指定位置–o xxx.bin xxx.o在最后有一步执行。
但这几步需要执行很多条指令,需要逐条输入这些指令而且修改了其中一个文件名之后,所有指令中相关的文件名都需要修改,非常麻烦,也容易出错。因此,采用Makefile文件,以实现对编译连接流程的控制。
Makefile文件没有后缀名,就叫“Makefile”,可以用笔记本写。基本元素是这样的:
(第一行)目标文件:源文件
(第二行)指令
即,
(第一行)target...: prerequisites ...
(第二行)command
除此之外,在开头可以定义“常数”,类似C语言的define,汇编语言的EQU。例如:
OBJS = xxx.o
使用时,将指令中xxx.o的地方都换成$(OBJS)。
还有[email protected]和$<,[email protected]是指目标文件,$<指源文件的第一个名字。可以写在指令里面,避免文件改名之后忘记都改。
例子;
# [[email protected] XXX]# rm -f kernel.bin
# [[email protected] XXX]# nasm -f elf -o kernel.o kernel.asm
# [[email protected] XXX]# nasm -f elf -o string.o string.asm
# [[email protected] XXX]# nasm -f elf -o klib.o klib.asm
# [[email protected] XXX]# gcc -c -o start.o start.c
# [[email protected] XXX]# ld -s -Ttext 0x30400 -o kernel.bin kernel.o string.o start.o klib.o
# [[email protected] XXX]# rm -f kernel.o string.o start.o
# [[email protected] XXX]#
ENTRYPOINT = 0x30400
ENTRYOFFSET = 0x400
# Programs, flags, etc.
MAKE = make
ASM = nasm
DASM = ndisasm
CC = gcc
LD = ld
ASMBFLAGS = -I boot/include
ASMKFLAGS = -I include -f elf
CFLAGS = -I include -c -fno-builtin
LDFLAGS = -s -Ttext $(ENTRYPOINT)
DASMFLAGS = -u -o $(ENTRYPOINT) -e $(ENTRYOFFSET)
OBJS = kernel.o string.o start.o klib.o
# All Phony Targets
.PHONY : everything final image clean realclean disasm all buildimg
# Default starting position
default :
$(MAKE) boot.bin
$(MAKE) loader.bin
$(MAKE) kernel.bin
$(MAKE) buildimg
clean :
rm $(OBJS) kernel.bin
realclean :
rm -f $(OBJS) $(TINIXBOOT) $(TINIXKERNEL)
disasm :
$(DASM) $(DASMFLAGS) $(TINIXKERNEL) > $(DASMOUTPUT)
# Write "boot.bin" & "loader.bin" into floppy image "TINIX.IMG"
# We assume that "TINIX.IMG" exists in current folder
buildimg :
dd if=/dev/zero of=tinix.img bs=512 count=2880
dd if=boot.bin of=tinix.img bs=512 count=1 conv=notrunc
mount -o loop -r -w tinix.img /mnt/floppy/
cp -f loader.bin /mnt/floppy/
cp -f kernel.bin /mnt/floppy
umount /mnt/floppy
boot.bin : boot.asm
$(ASM) $(ASMBFLAGS) -o [email protected] $<
loader.bin : loader.asm
$(ASM) $(ASMBFLAGS) -o [email protected] $<
kernel.bin : $(OBJS)
$(LD) $(LDFLAGS) -o kernel.bin $(OBJS)
kernel.o :kernel.asm
$(ASM) $(ASMKFLAGS) -o [email protected] $<
string.o :string.asm
$(ASM) $(ASMKFLAGS) -o [email protected] $<
klib.o: klib.asm
$(ASM) $(ASMKFLAGS) -o [email protected] $<
start.o: start.c
$(CC) -c -o [email protected] $<
[图片上传失败...(image-157d4e-1513048624585)]
参考资料:
http://m.blog.****.net/ruglcc/article/details/7814546?from=singlemessage&isappinstalled=0
《Orange'S:一个操作系统的实现》