学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
源码结构
- 配书代码包 :第4章 \ 程序 \ 程序4-4
程序4-4 源码结构
main.c
#include "lib.h"
#include "printk.h"
#include "gate.h"
void Start_Kernel(void)
{
. . .
color_printk(YELLOW,BLACK,"Hello\t\t World!\n");
i = 1/0;
while(1)
;
}
测试运行
-
反汇编
反汇编 查看 color_printk函数调用.pngobjdump -D system
查看color_printk
函数调用情况
-
当遇到 1/0 除法错误时,触发中断,在屏幕显示黑底红字的错误信息
程序4-4 运行结果"Unknown interrupt or fault at RIP\n"
[anno@localhost bootloader]$ make
nasm boot.asm -o boot.bin
nasm loader.asm -o loader.bin
[anno@localhost kernel]$ make
gcc -E head.S > head.s
as --64 -o head.o head.s
gcc -mcmodel=large -fno-builtin -m64 -c main.c
main.c: In function ‘Start_Kernel’:
main.c:72: warning: division by zero
gcc -mcmodel=large -fno-builtin -m64 -c printk.c
ld -b elf64-x86-64 -z muldefs -o system head.o main.o printk.o -T Kernel.lds
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin
[anno@localhost 4-4]$ ls
bochsrc boot.img bootloader kernel media
[anno@localhost 4-4]$ sudo mount boot.img media -t vfat -o loop
[anno@localhost 4-4]$ sudo cp bootloader/loader.bin media
[anno@localhost 4-4]$ sync
[anno@localhost 4-4]$ sudo cp bootloader/boot.bin media
[anno@localhost 4-4]$ sync
[anno@localhost 4-4]$ sudo cp kernel/kernel.bin media
[anno@localhost 4-4]$ sync
[anno@localhost 4-4]$ bochs -f ./bochsrc
源码分析
程序4-4 代码功能
-
模块
setup_IDT
负责往IDT(中断描述符表)填入中断描述符(单个表项占用16Byte
),中断描述符的格式参考(Figure 6-7. 64-Bit IDT Gate Descriptors
); -
目前,只写了一个中断处理程序
ignore_int
,功能是在发生中断时在屏幕显示黑底红字的错误信息"Unknown interrupt or fault at RIP\n"
,并随即进入死循环; -
根据描述符格式要求,现在利用
ignore_int
所在的内核数据段选择子0x10
以及ignore_int
的入口偏移地址,来创建中断描述符,并且往目前的IDT表的全部256个表项都填入这个相同的描述符(即目前无论发什么异常错误,都调用的是ignore_int
)
程序4-4 源码解析
内存示意图
程序4-4 内存示意图.pngsetup_IDT :格式化中断描述符
程序4-4 setup_IDT.pngignore_int :中断处理程序
程序4-4 ignore_int.png-
color_printk
的函数原型定义在源码文件kernel\printk.h
中 - 在
kernel\main.c
文件中,通过#include "printk.h"
导入了这个头文件,使用color_printk(YELLOW,BLACK,"Hello\t\t World!\n");
进行函数调用,这是C语言的做法; - 在
kernel\head.S
文件中,通过寄存器传递输入参数,使用汇编语句callq color_printk
进行函数调用,这是汇编里的 callq + 标号名的做法; - 在反汇编之后,可以看到全部的源码文件被集合到了一起,大家都是汇编、大家都是机器码,这就是为什么可以用callq + 标号名了;
setup_TSS64 :格式化TSS描述符,并填入GDT表
程序4-4 setup_TSS64.png参考资料
- IA-32e 中断处理过程 以及 IDT 中断描述符格式
Intel® 64 and IA-32 Architectures
Software Developer’s Manual
Volume 3 (3A, 3B, 3C & 3D): System Programming Guide
Figure 6-3. Interrupt Procedure Call
Figure 6-7. 64-Bit IDT Gate Descriptors
6.2 EXCEPTION AND INTERRUPT VECTORS
7.2.2 TSS Descriptor
7.2.2 TSS Descriptor
- 汇编指令 lea
lea
网友评论