第八回 | 烦死了又要重新设置一遍 idt 和 gdt
新读者看这里,老读者直接跳过。
本系列会以一个读小说的心态,从开机启动后的代码执行顺序,带着大家阅读和赏析 Linux 0.11 全部核心代码,了解操作系统的技术细节和设计思想。
你会跟着我一起,看着一个操作系统从啥都没有开始,一步一步最终实现它复杂又精巧的设计,读完这个系列后希望你能发出感叹,原来操作系统源码就是这破玩意。
以下是已发布文章的列表,详细了解本系列可以先从开篇词看起。
本系列的 GitHub 地址如下(文末阅读原文可直接跳转)
https://github.com/sunym1993/flash-linux0.11-talk
------- 正文开始 -------
lidt idt_48
lgdt gdt_48
mov al,#0xD1 ; command write
out #0x64,al
mov al,#0xDF ; A20 on
out #0x60,al
mov ax,#0x0001
lmsw ax
jmpi 0,8
_pg_dir:
_startup_32:
mov eax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
lss esp,_stack_start
long user_stack[4096 >> 2];
struct
{
long *a;
short b;
}
stack_start = {&user_stack[4096 >> 2], 0x10};
call setup_idt ;设置中断描述符表
call setup_gdt ;设置全局描述符表
mov eax,10h
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
lss esp,_stack_start
setup_idt:
lea edx,ignore_int
mov eax,00080000h
mov ax,dx
mov dx,8E00h
lea edi,_idt
mov ecx,256
rp_sidt:
mov [edi],eax
mov [edi+4],edx
add edi,8
dec ecx
jne rp_sidt
lidt fword ptr idt_descr
ret
idt_descr:
dw 256*8-1
dd _idt
_idt:
DQ 256 dup(0)
_gdt:
DQ 0000000000000000h ;/* NULL descriptor */
DQ 00c09a0000000fffh ;/* 16Mb */
DQ 00c0920000000fffh ;/* 16Mb */
DQ 0000000000000000h ;/* TEMPORARY - don't use */
DQ 252 dup(0)
jmp after_page_tables
...
after_page_tables:
push 0
push 0
push 0
push L6
push _main
jmp setup_paging
L6:
jmp L6那就是开启分页机制,并且跳转到 main 函数!
这可太令人兴奋了!开启分页后,配合着之前讲的分段,就构成了内存管理的最最底层的机制。而跳转到 main 函数,标志着我们正式进入 c 语言写的操作系统核心代码!
欲知后事如何,且听下回分解。
------- 本回扩展资料 -------
保护模式下逻辑地址到线性地址(不开启分页时就是物理地址)的转化,看 Intel 手册:
Volume 3 Chapter 3.4 Logical And Linear Addresses
段描述符结构和详细说明,看 Intel 手册:
Volume 3 Chapter 3.4.5 Segment Descriptors
对操作系统如何编译的,比如好奇那个 system 是怎么来的,可以尝试理解一下 Linux 0.11 源码中的 Makefile,这个我就不展开讲了,我们把更多经历,放在操作系统是怎么一步一步构建起来的这个过程。
------- 关于本系列 -------
本系列的开篇词看这
本系列的扩展资料看这(也可点击阅读原文),这里有很多有趣的资料、答疑、互动参与项目,持续更新中,希望有你的参与。
https://github.com/sunym1993/flash-linux0.11-talk
本系列全局视角
最后,祝大家都能追更到系列结束,只要你敢持续追更,并且把每一回的内容搞懂,我就敢让你在系列结束后说一句,我对 Linux 0.11 很熟悉。
另外,本系列完全免费,希望大家能多多传播给同样喜欢的人,同时给我的 GitHub 项目点个 star,就在阅读原文处,这些就足够让我坚持写下去了!我们下回见。