这一节主要装载GDT。
所需要的文件在Github:https://github.com/yongkangluo/Ubuntu20.04OS/tree/main/Files/Lec3-GDT
基本概念
1. GDT && GDTR && Segment Descriptor
全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。
“The Global Descriptor Table (GDT) is a binary data structure specific to the IA-32 and x86-64 architectures. It contains entries telling the CPU about memory segments. A similar Interrupt Descriptor Table exists containing task and interrupt descriptors.”+
GDT 由 GDTR 寄存器中的值指向。这是使用 LGDT 汇编指令加载的,该指令的参数是指向 GDT 描述符结构的指针。
其中GDT里装的东西是 段描述符 (Segment Descriptor)
Segment Descriptor:
2. 具体配置
gdt.h:主要是对一些初始参数的设定和配置。
gdt.c:
//gdt.c:
#include <lunaix/arch/gdt.h>
#include <stdint.h>
#define GDT_ENTRY 5
uint64_t _gdt[GDT_ENTRY];
uint16_t _gdt_limit = sizeof(_gdt);
void _set_gdt_entry(uint32_t index, uint32_t base, uint32_t limit, uint32_t flags){
_gdt[index] = SEG_BASE_H(base) | flags | SEG_LIM_H(limit) | SEG_BASE_M(base);
_gdt[index] <<= 32;
_gdt[index] |= SEG_BASE_L(base) | SEG_LIM_L(limit);
}
void _init_gdt(){
_set_gdt_entry(0, 0, 0, 0);
_set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE);
_set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA);
_set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE);
_set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA);
}
这里初始化了四块段地址。这是构造GDT表的过程,包括段描述符的生成。下面就要把GDT的地址加载到GDTR中。boot.S相关代码如下:
call _kernel_init
subl $0x6, %esp
// 因为 GDTR 是 48 bit,所以在栈上先分配 6 字节
movl $_gdt, 2(%esp)
// 先加载地址偏移量
movw _gdt_limit, %ax
movw %ax, (%esp)
// 再加载size
lgdt (%esp)
addl $0x6, %esp
// 栈回复
movw $0x10, %cx
movw %cx, %es
movw %cx, %ds
movw %cx, %fs
movw %cx, %gs
movw %cx, %ss
// 初始化段寄存器
pushw $0x08
pushl $_after_gdt
retf
// 这里进行的是跳转
_after_gdt:
pushl %ebx
call _kernel_main
具体的代码在github都用,其中文件目录如下所示。
.
├── arch
│ ├── boot.S
│ ├── gdt.c
│ ├── multiboot.h
│ └── x86
├── bochs.cfg
├── config-grub.sh
├── dump
├── GRUB_TEMPLATE
├── hal
├── includes
│ ├── libc
│ └── lunaix
│ ├── arch
│ │ └── gdt.h![请添加图片描述](https://img-blog.csdnimg.cn/0e16d0c2e97644d4b5ae17faa810a78f.jpeg)
│ └── tty
│ └── tty.h
├── kernel
│ ├── kernel.c
│ └── tty
│ └── tty.c
├── libs
├── linker.ld
└── makefile
之后利用make all生成文件,然后make run 或者 make debug-bochs c 即可运行成功。
方法主要跟着B站Up主做的,B站视频链接在:https://www.bilibili.com/video/BV1jL4y1s7X6/?spm_id_from=333.788&vd_source=72ce864f895f9fbf22b81450817f2875