⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 program-kernel-head-comment.html

📁 学习linux的工具书
💻 HTML
字号:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
   <meta name="Author" content="Edward Fu">
   <meta name="GENERATOR" content="Mozilla/4.05 [zh-CN] (X11; I; Linux 2.1.127 i686) [Netscape]">
   <title>Freesoft Linux FAQ -- 内核原代码head.s部分的注释</title>
</head>
<body>
/*
<br>*&nbsp; head.s contains the 32-bit startup code.
<br>*
<br>* NOTE!!! Startup happens at absolute address 0x00000000, which is
also where
<br>* the page directory will exist. The startup code will be overwritten
by
<br>* the page directory.
<br>*/
<br>.text
<br>.globl _idt,_gdt,_pg_dir
<br>_pg_dir:
<br>startup_32:
<br>movl $0x10,%eax&nbsp;&nbsp; @@ds,es,fs,gs指向内核数据段
<br>mov %ax,%ds
<br>mov %ax,%es
<br>mov %ax,%fs
<br>mov %ax,%gs
<br>lss _stack_start,%esp&nbsp; @@ds送ss&nbsp; esp 指向stack_start (在sched.c定义)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@进入保护模式的堆栈段的第一次变化,很奇怪
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@为什么堆栈段也可正向增涨?
<br>call setup_idt
<br>call setup_gdt
<br>movl $0x10,%eax&nbsp; # reload all the segment registers
<br>mov %ax,%ds&nbsp; # after changing gdt. CS was already
<br>mov %ax,%es&nbsp; # reloaded in 'setup_gdt' @@ 有reload??
<br>mov %ax,%fs
<br>mov %ax,%gs
<br>lss _stack_start,%esp
<br>xorl %eax,%eax
<br>1: incl %eax&nbsp; # check that A20 really IS enabled
<br>movl %eax,0x000000
<br>cmpl %eax,0x100000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @@这是怎么测的 0x100000为什么值,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@明白,a20 not
<br>enable,0x000000就是0x100000
<br>je 1b
<br>movl %cr0,%eax&nbsp; # check math chip
<br>andl $0x80000011,%eax # Save PG,ET,PE
<br>testl $0x10,%eax
<br>jne 1f&nbsp;&nbsp; # ET is set - 387 is present
<br>orl $4,%eax&nbsp; # else set emulate bit
<br>1: movl %eax,%cr0
<br>jmp after_page_tables&nbsp;&nbsp; @@注意,用jmp 不call,不返回
<p>/*
<br>*&nbsp; setup_idt
<br>*
<br>*&nbsp; sets up a idt with 256 entries pointing to
<br>*&nbsp; ignore_int, interrupt gates. It then loads
<br>*&nbsp; idt. Everything that wants to install itself
<br>*&nbsp; in the idt-table may do so themselves. Interrupts
<br>*&nbsp; are enabled elsewhere, when we can be relatively
<br>*&nbsp; sure everything is ok. This routine will be over-
<br>*&nbsp; written by the page tables.
<br>*/
<br>setup_idt:
<br>lea ignore_int,%edx
<br>movl $0x00080000,%eax
<br>movw %dx,%ax&nbsp; /* selector = 0x0008 = cs */
<br>movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@&nbsp; ignore_int 低16-->ax&nbsp; 高16-->edx高字
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
8e00-->dx&nbsp;&nbsp; 8-->eax高字
<br>lea _idt,%edi
<br>mov $256,%ecx
<br>rp_sidt:
<br>movl %eax,(%edi)
<br>movl %edx,4(%edi)
<br>addl $8,%edi
<br>dec %ecx
<br>jne rp_sidt
<br>lidt idt_descr
<br>ret
<p>/*
<br>*&nbsp; setup_gdt
<br>*
<br>*&nbsp; This routines sets up a new gdt and loads it.
<br>*&nbsp; Only two entries are currently built, the same
<br>*&nbsp; ones that were built in init.s. The routine
<br>*&nbsp; is VERY complicated at two whole lines, so this
<br>*&nbsp; rather long comment is certainly needed :-).
<br>*&nbsp; This routine will beoverwritten by the page tables.
<br>*/
<br>setup_gdt:
<br>lgdt gdt_descr
<br>ret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @@跳到main函数
<p>.org 0x1000
<br>pg0:
<p>.org 0x2000
<br>pg1:
<p>.org 0x3000
<br>pg2:&nbsp; # This is not used yet, but if you
<br>&nbsp; # want to expand past 8 Mb, you'll have
<br>&nbsp; # to use it.
<p>.org 0x4000
<br>after_page_tables:
<br>pushl $0&nbsp; # These are the parameters to main :-)
<br>pushl $0
<br>pushl $0
<br>pushl $L6&nbsp; # return address for main, if it decides to.
<br>pushl $_main
<br>jmp setup_paging&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @@再jmp
<br>L6:
<br>jmp L6&nbsp;&nbsp; # main should never return here, but
<br>&nbsp;&nbsp;&nbsp; # just in case, we know what happens.
<p>/* This is the default interrupt "handler" :-) */
<br>.align 2
<br>ignore_int:
<br>incb 0xb8000+160&nbsp; # put something on the screen
<br>movb $2,0xb8000+161&nbsp; # so that we know something
<br>iret&nbsp;&nbsp;&nbsp; # happened
<br>&nbsp;
<p>/*
<br>* Setup_paging
<br>*
<br>* This routine sets up paging by setting the page bit
<br>* in cr0. The page tables are set up, identity-mapping
<br>* the first 8MB. The pager assumes that no illegal
<br>* addresses are produced (ie >4Mb on a 4Mb machine).
<br>*
<br>* NOTE! Although all physical memory should be identity
<br>* mapped by this routine, only the kernel page functions
<br>* use the >1Mb addresses directly. All "normal" functions
<br>* use just the lower 1Mb, or the local data space, which
<br>* will be mapped to some other place - mm keeps track of
<br>* that.
<br>*
<br>* For those with more memory than 8 Mb - tough luck. I've
<br>* not got it, why should you :-) The source is here. Change
<br>* it. (Seriously - it shouldn't be too difficult. Mostly
<br>* change some constants etc. I left it at 8Mb, as my machine
<br>* even cannot be extended past that (ok, but it was cheap :-)
<br>* I've tried to show which constants to change by having
<br>* some kind of marker at them (search for "8Mb"), but I
<br>* won't guarantee that's all :-( )
<br>*/
<br>.align 2
<br>setup_paging:
<br>movl $1024*3,%ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@pg_dir pg_table 清零
<br>xorl %eax,%eax
<br>xorl %edi,%edi&nbsp;&nbsp; /* pg_dir is at 0x000 */
<br>cld;rep;stosl
<br>movl $pg0+7,_pg_dir&nbsp; /* set present bit/user r/w */
<br>movl $pg1+7,_pg_dir+4&nbsp; /*&nbsp; --------- " " --------- */
<br>movl $pg1+4092,%edi
<br>movl $0x7ff007,%eax&nbsp; /*&nbsp; 8Mb - 4096 + 7 (r/w user,p) */
<br>std
<br>1: stosl&nbsp;&nbsp; /* fill pages backwards - more efficient :-) */
<br>subl $0x1000,%eax
<br>jge 1b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ greater or equal
<br>xorl %eax,%eax&nbsp; /* pg_dir is at 0x0000 */
<br>movl %eax,%cr3&nbsp; /* cr3 - page directory start */
<br>movl %cr0,%eax
<br>orl $0x80000000,%eax
<br>movl %eax,%cr0&nbsp; /* set paging (PG) bit */
<br>ret&nbsp;&nbsp; /* this also flushes prefetch-queue */
<p>@@页目录pg_dir=0 仅两项(8M),
<br>@@pg1,pg0页表逆向填充,pg0的首页仍为零
<br>@@这样映射,线性地址=物理地址
<p>.align 2
<br>.word 0
<br>idt_descr:
<br>.word 256*8-1&nbsp; # idt contains 256 entries
<br>.long _idt
<br>.align 2
<br>.word 0
<br>gdt_descr:
<br>.word 256*8-1&nbsp; # so does gdt (not that that's any&nbsp; @@和前面head.S差一??
<br>.long _gdt&nbsp; # magic number, but it works for me :^)
<p>.align 3
<br>_idt: .fill 256,8,0&nbsp; # idt is uninitialized
<p>_gdt: .quad 0x0000000000000000 /* NULL descriptor */
<br>.quad 0x00c09a00000007ff /* 8Mb */
<br>.quad 0x00c09200000007ff /* 8Mb */
<br>.quad 0x0000000000000000 /* TEMPORARY - don't use */
<br>.fill 252,8,0&nbsp;&nbsp; /* space for LDT's and TSS's etc */
<br>@@内核 逻辑地址(不含段寄存器)=线性地址
<br>&nbsp;
<br>&nbsp;
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -