[OS64位][019]源码阅读:程序4-4 异常/中断(一)显示"Unknown interrupt or fault at RIP\n"...

学习笔记

使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171

源码结构

  • 配书代码包 :第4章 \ 程序 \ 程序4-4
10191360-f079ca1891ee4faf.png
程序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)
        ;
}

测试运行

  • 反汇编 objdump -D system 查看 color_printk 函数调用情况

    10191360-884a2c68b86082c9.png
    反汇编 查看 color_printk函数调用.png

  • 当遇到 1/0 除法错误时,触发中断,在屏幕显示黑底红字的错误信息"Unknown interrupt or fault at RIP\n"

    10191360-e3e850d3ad94be2c.png
    程序4-4 运行结果

[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 源码解析

内存示意图

10191360-44f7b0dc9f71d66a.png
程序4-4 内存示意图.png

setup_IDT :格式化中断描述符

10191360-f30587d1fc78b62a.png
程序4-4 setup_IDT.png

ignore_int :中断处理程序

10191360-f14314bc045b68dd.png
程序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表

10191360-9810f296be54a1d8.png
程序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

10191360-ce24f3e35719ac1a.png
Figure 6-3. Interrupt Procedure Call

10191360-50884108480afb09.png
Figure 6-7. 64-Bit IDT Gate Descriptors

6.2 EXCEPTION AND INTERRUPT VECTORS

10191360-4e1852c62ad705ec.png
7.2.2 TSS Descriptor

7.2.2 TSS Descriptor

扫描二维码关注公众号,回复: 6432555 查看本文章
  • 汇编指令 lea
10191360-f250626b33ae2be3.png
lea

猜你喜欢

转载自blog.csdn.net/weixin_33717117/article/details/90968824