当前位置: 首页 > 工具软件 > Clean-macOS > 使用案例 >

搭建MacOS中开发操作系统的环境

彭雨华
2023-12-01

这里的环境我参照的是《操作系统真象还原》。

C 编译器

C语言的编译器我用的是gcc,但是如果使用MacOS自带的gcc的话有一个问题。书上加载内核时是按照elf32格式解析的,关于elf32的文件格式可以去看这位大哥的文章。MacOS自带的gcc编译器产生的是苹果电脑上的可执行文件格式(即Mach-O 64-bit executable x86_64,我的机器是64位)。这时我们就需要一个交叉编译器。经过查阅资料,我得知了MacOS上的交叉编译器叫做i386-elf-gcc,可以通过brew install i386-elf-gcc安装,但是却出现了一条警告:

Warning: Use x86_64-elf-gcc instead of deprecated i386-elf-gcc

大意是说i386-elf-gcc已被废弃,现在已被更新为x86_64-elf-gcc。我们不管,继续安装。但是按照名字来看,这个x86_64-elf-gcc貌似是编译出elf64文件格式的,32位和64位在加载内核上还是有区别的。果然,编译出的文件格式为ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped。通过百度,我了解到可以通过-m32来指定输出32位文件。撒花……等等!这个链接器又“罢工”了。这时我们的编译器应该使用x86_64-elf-ld了,可是它为什么提示没有-m32这个参数呢?于是我查阅了一下文档,原来需要使用-m elf_i386参数才行。大功告成!

C++ 编译器

其实我个人还是更加喜欢使用C++,只要安装了x86_64-elf-gcc,那么就安装了x86_64-elf-g++,使用这个编译就好啦。

汇编编译器

这里的汇编编译器我们使用的是nasm,只要通过brew install nasm安装,编译时添加一个新的参数-f elf_i386就行啦!

关于内核加载的地址(第5章)

等我把加载内核的代码写完了后发现加载器却罢工了,不知道大家有没有遇到这个问题呢?别急,我们把内核的加载地址往后移0x1000个字节,即0xc0002500,然后再把代码中的和dd命令中的扇区数从4改成6。当当当,能运行啦!因为书上默认的加载器的代码不会超过2.0KB,但是可能是因为工具换了的原因,我编译出的代码居然有2.2KB!这还能运行?所以赶紧把地址改了过来。

关于内存容量地址和GDT地址勘误

书中所写的检测完内存容量的地址是存储在0xb00(第5章),但是我在这个地址读出的内容居然是0!经过一遍一遍地审视代码,终于发现了作者计算地址时似乎少算了开头jmp loader_start的3个字节,因此真正的地址应该为0xb03!同样GDT的地址(第11章)也要往后移3个字节!

使用Makefile

Makefile就相当于是一个高级的“批处理文件”,书中的Makefile是到了第8章才开始讲的,不过我觉得,这个东西还是早用早受益,以下附上我编写的Makefile(我现在看到第11章):

ASM = nasm
GCC = x86_64-elf-gcc
G++ = x86_64-elf-g++
LD = x86_64-elf-ld
ASMFLAGS = -f elf32
CFLAGS = -m32 -c -fno-builtin
LDFLAGS = -m elf_i386 -Ttext 0xc0002500 -e main
OBJS = kernel/main.o kernel/console.o kernel/init.o kernel/interrupt.o kernel/memory.o kernel/sync.o kernel/thread.o kernel/tss.o kernel/kernel.o kernel/switch.o device/keyboard.o device/timer.o lib/string.o lib/kernel/bitmap.o lib/kernel/fifo.o lib/kernel/list.o lib/kernel/print.o

boot/mbr.bin: boot/mbr.S Makefile
	$(ASM) -o boot/mbr.bin boot/mbr.S

boot/loader.bin: boot/loader.S Makefile
	$(ASM) -o boot/loader.bin boot/loader.S

kernel/main.o: kernel/main.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/main.o kernel/main.cpp

kernel/console.o: kernel/console.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/console.o kernel/console.cpp

kernel/init.o: kernel/init.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/init.o kernel/init.cpp

kernel/interrupt.o: kernel/interrupt.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/interrupt.o kernel/interrupt.cpp

kernel/memory.o: kernel/memory.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/memory.o kernel/memory.cpp

kernel/sync.o: kernel/sync.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/sync.o kernel/sync.cpp

kernel/thread.o: kernel/thread.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/thread.o kernel/thread.cpp

kernel/tss.o: kernel/tss.cpp Makefile
	$(G++) $(CFLAGS) -o kernel/tss.o kernel/tss.cpp

kernel/kernel.o: kernel/kernel.S Makefile
	$(ASM) $(ASMFLAGS) -o kernel/kernel.o kernel/kernel.S

kernel/switch.o: kernel/switch.S Makefile
	$(ASM) $(ASMFLAGS) -o kernel/switch.o kernel/switch.S

device/keyboard.o: device/keyboard.cpp Makefile
	$(G++) $(CFLAGS) -o device/keyboard.o device/keyboard.cpp

device/timer.o: device/timer.cpp Makefile
	$(G++) $(CFLAGS) -o device/timer.o device/timer.cpp

lib/string.o: lib/string.cpp Makefile
	$(G++) $(CFLAGS) -o lib/string.o lib/string.cpp

lib/kernel/bitmap.o: lib/kernel/bitmap.cpp Makefile
	$(G++) $(CFLAGS) -o lib/kernel/bitmap.o lib/kernel/bitmap.cpp

lib/kernel/fifo.o: lib/kernel/fifo.cpp Makefile
	$(G++) $(CFLAGS) -o lib/kernel/fifo.o lib/kernel/fifo.cpp

lib/kernel/list.o: lib/kernel/list.cpp Makefile
	$(G++) $(CFLAGS) -o lib/kernel/list.o lib/kernel/list.cpp

lib/kernel/print.o: lib/kernel/print.S Makefile
	$(ASM) $(ASMFLAGS) -o lib/kernel/print.o lib/kernel/print.S

kernel/main.bin: $(OBJS) Makefile
	$(LD) $(LDFLAGS) -o kernel/main.bin $(OBJS)

run: bochsrc.disk boot.img boot/mbr.bin boot/loader.bin kernel/main.bin Makefile
	dd if=boot/mbr.bin of=boot.img bs=512 count=1 conv=notrunc
	dd if=boot/loader.bin of=boot.img bs=512 count=7 seek=2 conv=notrunc
	dd if=kernel/main.bin of=boot.img bs=512 count=200 seek=9 conv=notrunc
	bochs -f bochsrc.disk

clean: Makefile
	-rm boot/mbr.bin
	-rm boot/loader.bin
	-rm kernel/*.o
	-rm device/*.o
	-rm lib/*.o
	-rm lib/kernel/*.o
	-rm kernel/main.bin

好啦,看到这里各位的环境都已经搭建好了吧。这本书的错误挺多的, 大家要敢于质疑,希望能尽快看到大家开发的操作系统。最后,点个赞再走吧~

 类似资料: