学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
源码文件
- 第3章\程序\程序3-4\
loader.asm
源码阅读:保护模式 -> IA-32e模式(或称长模式)
代码清单3-28 Line 42 ~ 53 : IA-32e模式的段结构
代码清单3-29 Line 495~513 : GO_TO_TMP_Protect
(在代码清单3-27执行后继续执行)
代码清单3-30 Line 574~595 : test support long mode or not
代码清单3-31 Line 514~532 : init template page table 0x90000
代码清单3-32 Line 533~545 : load GDTR
代码清单3-33 Line 546~551 : open PAE
代码清单3-34 Line 552~556 : load cr3
代码清单3-35 Line 557~564 : enable long-mode
代码清单3-36 Line 565~570 : open PE and paging
代码清单3-37 Line 572 : 从Loader跳转到内核程序
[SECTION gdt64]
LABEL_GDT64: dq 0x0000000000000000
LABEL_DESC_CODE64: dq 0x0020980000000000
LABEL_DESC_DATA64: dq 0x0000920000000000
GdtLen64 equ $ - LABEL_GDT64
GdtPtr64 dw GdtLen64 - 1
dd LABEL_GDT64
SelectorCode64 equ LABEL_DESC_CODE64 - LABEL_GDT64
SelectorData64 equ LABEL_DESC_DATA64 - LABEL_GDT64
[SECTION .s32]
[BITS 32]
GO_TO_TMP_Protect:
;======= go to tmp long mode
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov esp, 7E00h
call support_long_mode
test eax, eax
jz no_support
;======= init temporary page table 0x90000
mov dword [0x90000], 0x91007
mov dword [0x90800], 0x91007
mov dword [0x91000], 0x92007
mov dword [0x92000], 0x000083
mov dword [0x92008], 0x200083
mov dword [0x92010], 0x400083
mov dword [0x92018], 0x600083
mov dword [0x92020], 0x800083
mov dword [0x92028], 0xa00083
;======= load GDTR
db 0x66
lgdt [GdtPtr64]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 7E00h
;======= open PAE
mov eax, cr4
bts eax, 5
mov cr4, eax
;======= load cr3
mov eax, 0x90000
mov cr3, eax
;======= enable long-mode
mov ecx, 0C0000080h ;IA32_EFER
rdmsr
bts eax, 8
wrmsr
;======= open PE and paging
mov eax, cr0
bts eax, 0
bts eax, 31
mov cr0, eax
jmp SelectorCode64:OffsetOfKernelFile
;======= test support long mode or not
support_long_mode:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
setnb al
jb support_long_mode_done
mov eax, 0x80000001
cpuid
bt edx, 29
setc al
support_long_mode_done:
movzx eax, al
ret
;======= no support
no_support:
jmp $
OffsetOfKernelFile equ 0x100000
关于IA-32e模式
IA-32e模式简化了保护模式的段结构,删减掉冗余的段基地址和段限长,使段直接覆盖整个线性地址空间,进而变成平坦地址空间
一旦激活IA-32e模式,软件便可重定位页表到物理内存空间的任何地方
CR4控制寄存器的第5位是PAE功能的标志位,置位该标志位可开启PAE(开启物理地址扩展功能)
加载页目录基地址到CR3控制寄存器
mov cr0, eax
,至此,处理器进入IA-32e模式需要一条跨段跳转/调用指令将CS段寄存器的值更新为IA-32e模式的代码段描述符
jmp SelectorCode64:OffsetOfKernelFile
参考资料
- 关于平坦模式
在平坦模式下,名义上不分段,但实际上是只分一个大段,在这种情况下,不管程序实际加载到哪里,代码段、数据段和栈段,其描述符的基地址都固定为
0x00000000