一、准备工具- bochs
- Virtual Machine
- nasm
- gcc
- ld
等。更多需要的工具已经放在码云开源仓库。 二、操作步骤1. 实现步骤- 完成引导程序开发
- 使用汇编语言两段子程序
- 使用C语言开发调用汇编子程序
- 编译程序,制作软盘镜像
- BIOS加载并运行汇编语言的引导程序
- 汇编语言程序从软盘读取10扇区,当中包含C语言程序
- 程序跳转到C语言的程序
- C调用汇编,实现清屏操作。
2. 重点(1) 汇编语言子程序实现[BITS 16]global io_hltglobal clear_screenclear_screen: ; 清屏 mov ax, 03h int 10h ;pop ecx ; jmp cxRETio_hlt:HLTRET
这段子程序实现了清屏、空循环功能。 为方便C的调用,再写一个头文件: #ifndef __UTILITIES_H_#define __UTILITIES_H_// 此处只提供函数声明// 函数实现在utilities.svoid io_hlt(void);void clear_screen(void);#endif
(2) 在C中调用汇编的方法#include 'utilities.h'void main(void){ clear_screen(); // clear screen fin: io_hlt(); /* call io_hlt */ goto fin;}
三、编译的重点TOOLPATH = ./tools/TARGET = ./target/SRC = ./src/LD=./env/bin/i686-elf-ld.exeCC=./env/bin/i686-elf-gcc.exeNASM=$(TOOLPATH)nasm.exeDD=$(TOOLPATH)dd.exeBOCHSPATH=$(TOOLPATH)bochs/MAKE =$(TOOLPATH)make.exe -rCOPY = copyDEL = del# LD编译选项LDFLAGS=-m elf_i386# GCC编译选项CCFLAGS=-march=i386 -m16 -mpreferred-stack-boundary=2 -ffreestandingASFLAGS=# 默认动作default : kernel.bin loader.bin kernel.o utilities.o loader.o# 汇编的函数 用来给C调用utilities.o: $(SRC)kernel/utilities.s$(NASM) $(ASFLAGS) -f elf32 -o $(TARGET)$@ $^kernel.o : $(SRC)kernel/kernel.c $(SRC)kernel/utilities.h$(CC) $(CCFLAGS) -o $(TARGET)kernel.o -c $(SRC)kernel/kernel.ckernel.bin : kernel.o utilities.o$(LD) $(LDFLAGS) -Ttext 0xC200 --oformat binary -o $(TARGET)$@ $(TARGET)kernel.o $(TARGET)utilities.oloader.o: $(SRC)boot/loader.s$(NASM) $(ASFLAGS) -f elf32 -o $(TARGET)$@ $^loader.bin : loader.o$(LD) $(LDFLAGS) -Ttext 0x7c00 --oformat binary -o $(TARGET)$@ $(TARGET)$^install :$(DD) if=$(TARGET)kernel.bin of=$(TARGET)os.img conv=notrunc bs=512 seek=1$(DD) if=$(TARGET)loader.bin of=$(TARGET)os.img conv=notrunc run : Makefilecd $(TOOLPATH) && bochs.bat && cd ..debug:cd $(TOOLPATH) && bochsdebug.bat && cd ..clean :cd $(TARGET) && del -f *
汇编编译器nasm生成 .o 文件, C编译器 gcc也生成 .o 文件, 通过LD进行链接,生成二进制文件。 3. 编译运行makemake install
这里还有点问题,生成的kernel.bin后进行下面操作: - 使用Virtual Box 加载 os.img 软盘镜像
- 把kernel.bin 拷贝到os.img
- 弹出虚拟软盘
make run
可以看到最后屏幕被清屏了。 也可以使用 make debug 调试,看一下内存情况: 在0xc200处设置断点: b 0xc200c
下图可以看到程序在0xc205处调用了 0xc220, 然后在0xc20b处进入空循环。 清屏效果:
|