📄 head.s
字号:
;***********************************************************;; 32 bit 内核环境: gdt ,idt ; pg_dir pgtable; tss;; Segment Descripters:; TSS; LDT 不使用; Code ; Data; ;*************************************************************global Start_OSglobal _gdt, _kpg_dirglobal _kpg_table,_pgt0,_pgt1extern _mainSECTION .text ; if no this , the ld can't find entry Start_OSStart_OS: ;mov ax,cs ; right, forgot this at first. didn't work :-) ;mov ds,ax ; 代码段描述符是不容许写的!!!!!! ;call setup_paging ;尽快开启分页 ;设置页目录,8M,2 entry mov dword[_kpg_dir],_pgt0+7 ;页表采用绝对定位 mov dword[_kpg_dir+4],_pgt1+7 ;3G+0- 3G+8M mov dword[_kpg_dir+768*4],_pgt0+7 mov dword[_kpg_dir+4+768*4],_pgt1+7 ;设置两个页表, 恒同映射 mov edi,_pgt0 ;+4092 mov eax,0x007 ;/* 8Mb - 4096 + 7 (r/w user,p) */ fill_pte: mov [edi],eax add eax,0x1000 ;页面号加1(物理页面号) add edi,4 cmp eax,0x800007 ;0x7ff007 jl fill_pte ;准备开启分页,设置cr3为页目录地址 mov eax,_kpg_dir ;/* pg_dir */ mov cr3,eax ;/* cr3 - page directory start */ ;开启分页 mov eax,cr0 or eax,0x80000000 mov cr0,eax ;/* set paging (PG) bit */ jmp page_flush ;这一句让内核在3G以上开始运行 page_flush: ;mov edx, 0x310a330a ;mov eax, 0xc00b8000 ;mov [eax],edx ;fush_after_paging_on:jmp fush_after_paging_on lgdt [gdt_descr] ; reload gdt with kernel gdt jmp pmode_flush pmode_flush: push dword 0 popf jmp 8:pmode_cs_flush ; cs<--8,code segment pmode_cs_flush: mov ax,0x10 ; ds<--15, data segment mov ds,ax ;die:jmp die mov es,ax mov ss,ax ;mov fs,ax ;mov gs,ax mov esp,_k_top ;4k 内核栈 mov eax,0 mov eax,0 call _main ;不可能运行到这里 never_here: jmp never_hereglobal __flush __flush: mov eax,cr3 mov cr3,eax ;/* cr3 - page directory start */ ret;*********************全局变量********************************** ;;section .dataalign 2 dw 0;伪gdt段的描述符,用于装载全局描述表寄存器GDTR; Limit dw 0; Liner_Base dd 0gdt_descr: dw 256*8-1 ; so does gdt (not that that's any dd _gdt ; magic number, but it works for me :^) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;全局描述符表;像linux 一样,我们不准备使用x86的分段机制;我们用4G的描述符绕过这个机制, 绝大多数cpu;只支持分页就是我们最好的理由; LIMITL DW 0 ;段界限低16位; BASEL DW 0 ;基地址低16位; BASEM DB 0 ;基地址中间8位; ATTRIB DB 0 ;段属性 P DPL(2) S TYPE(4); LIMITH DB 0 ;G D/B 0 AVL ,段界限的高4位16-19bits; BASEH DB 0 ;基地址的高8位section .data_gdt: dw 0,0,0,0 ; CPU 不使用第一个段描述符 ;见IA-32 Volume 3, 3.5.1. Segment Descriptor Tables ;kernel code dw 0xFFFF ; 4G - limit=2047 (2048*4096=8Mb) dw 0x0000 ; base address=0 db 0x00 ; base address=0 db 0x9A ; code read//exec || 1 00(dpl)//1(code/data) 1010 db 0xCF ; 1100,粒度4k,32bit默认操作数,1111(4G), db 0x00 ; base ;kernel data dw 0xFFFF ; 4G - limit=2047 (2048*4096=8Mb) dw 0x0000 ; base address=0 db 0x00 ; base address=0 db 0x92 ; data read/write || 1 00(dpl)/1(code/data) 1010 db 0xCF ; 1100,粒度4k,32bit默认操作数,1111(4G), db 0x00 ; base ;user code ;user data times 252*8 db 0 ;/* space for LDT's and TSS's etc */;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Paging page dir; cr3----> |----------| page table; |----------|\_______\ |--------| |->|------|; |----------|/ / |--------| ----| |物理页| ; |----------| ..... | |------|; .... |; |----------|\_______\ |--------| | ; |----------|/ / |--------|-----|; |----------| |--------|-------->|-----|; ....... ...... | |; |-----|;上面的图示演示一种特殊的页映射;page dir :4G空间, 1024 项,每个entry 有4m空间,占用4k;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;页目录表表项格式 ;31-----12 11--9 8 7 6 5 4 3 2 1 0 ;物理页码 AVL G PS 0 A PCD PWT U/S R/W P ;;---最高20位(位12—位31)包含物理地址空间页的页码,也就是物理地址的高20位。;---低12位包含页的属性,属性中内容为0的位保留位必须设置为0。;---AVL字段供软件使用。;---G(Pentium Pro)置1代表是一个全局页. 我们置0.;---PS Page Size. ;0代表4k页,page dir entry 指向一个页表. 1代表4M页,page dir entry 指向页.;---A=1表示已访问过对应的物理页. 处理器永不清除A位,在访问时置A位.;通过周期性地检测及清除A位,操作系统就可确定哪些页在最近一段时间未被访问过;---PCD page-level cache disable. 为0时对应的页表或页可以被cache. ;i/o 内存一般情况下不容许cache.;---PWT page write-through. 如果置1, 写通cache策略使能, 否则使用write-back.;---U/S位指示该表项所指定的页是否是用户级页。;若U/S=1,表项所指定的页是用户级页,可由任何特权级下执行的程序访问;;如果U/S=0,表项所指定的页是系统级页,只能由系统特权级下执行的程序访问;---R/W位指示该表项所指定的页是否可读、写或执行。;若R/W=1,对表项所指定的页可进行读、写或执行;;若R/W=0,对表项所指定的页可读或执行,但不能对该指定的页写入。;但是,R/W位对页的写保护只在处理器处于用户特权级时发挥作用;;当处理器处于系统特权级时,R/W位被忽略,即总可以读、写或执行。 ;---P位表示该表项是否已经建立映射.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -