// 这是内核执行头程序 // Created by longjin. // 2022/01/20 .section .text .global _start _start: // 初始化寄存器 mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %ss mov $0x7e00, %esp // === 加载GDTR ==== lgdt GDT_POINTER(%rip) //这里我没搞明白rip相对寻址, 看了文档,大概是用来实现PIC的(position independent code) // === 加载IDTR ==== lidt IDT_POINTER(%rip) mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %ss mov %ax, %gs movq $0x7e00, %rsp // ==== 加载CR3寄存器 movq $0x101000, %rax //设置页目录基地址 movq %rax, %cr3 movq switch_seg(%rip), %rax // 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器 // 实在是太妙了!Amazing! pushq $0x08 //段选择子 pushq %rax lretq // 64位模式的代码 switch_seg: .quad entry64 entry64: movq $0x10, %rax movq %rax, %ds movq %rax, %es movq %rax, %gs movq %rax, %ss movq $0xffff800000007e00, %rsp //rsp的地址 // 切换到内核主程序 movq go_to_kernel(%rip), %rax pushq $0x08 pushq %rax lretq go_to_kernel: .quad Start_Kernel // 初始化页表 .align 8 //设置为8byte对齐 .org 0x1000 //设置页表位置为内核执行头程序的0x1000处 __PML4E: .quad 0x102007 // 系统访问,可读写,已存在, 地址在31~12位 .fill 255,8,0 .quad 0x102007 .fill 255,8,0 .org 0x2000 __PDPTE: .quad 0x103003 // 用户访问,可读写,已存在 .fill 511,8,0 .org 0x3000 __PDE: .quad 0x000083 // 用户访问,可读写,已存在 .quad 0x200083 .quad 0x400083 .quad 0x600083 .quad 0x800083 .quad 0xe0000083 /*0x a00000*/ .quad 0xe0200083 .quad 0xe0400083 .quad 0xe0600083 /*0x1000000*/ .quad 0xe0800083 .quad 0xe0a00083 .quad 0xe0c00083 .quad 0xe0e00083 .fill 499,8,0 // GDT表 .section .data .global GDT_Table // 使得GDT可以被外部程序引用或者访问 GDT_Table: .quad 0x0000000000000000 // 0 空描述符 00 .quad 0x0020980000000000 // 1 内核64位代码段描述符 08 .quad 0x0000920000000000 // 2 内核64位数据段描述符 10 .quad 0x0020f80000000000 // 3 用户64位代码段描述符 18 .quad 0x0000f20000000000 // 4 用户64位数据段描述符 20 .quad 0x00cf9a000000ffff // 5 内核32位代码段描述符 28 .quad 0x00cf92000000ffff // 6 内核32位数据段描述符 30 .fill 10, 8, 0 // 8~9 TSS(跳过了第七段) 重复十次填充8字节的空间,赋值为0 GDT_END: GDT_POINTER: GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT的大小 GDT_BASE: .quad GDT_Table // IDT 表 .global IDT_Table IDT_Table: .fill 512, 8, 0 // 设置512*8字节的IDT表的空间 IDT_END: IDT_POINTER: IDT_LIMIT: .word IDT_END - IDT_Table - 1 IDT_BASE: .quad IDT_Table // 64位的TSS表 .global TSS64_Table TSS64_Table: .fill 13, 8, 0 TSS64_END: TSS64_POINTER: TSS64_LIMIT: .word TSS64_END - TSS64_Table - 1 TSS64_BASE: .quad TSS64_Table