实验12 Linux内核启动分析综述
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验12 Linux内核启动分析
实验目的
就boot.s和head.s了解Linux启动的部分工程
实验步骤
下载源码
分析源码
源码分析结果
head.s
# head.s contains the 32-bit startup code.
# Two L3 task multitasking. The code of tasks are in kernel area,
# just like the Linux. The kernel code is located at 0x10000.
;头文件包含32位的启动代码
;两个L3 分配多个任务,就像linux,它的任务代码在核心区域
;核心代码在0x10000的地址上
SCRN_SEL = 0x18
TSS0_SEL = 0x20
LDT0_SEL = 0x28
TSS1_SEL = 0X30
LDT1_SEL = 0x38
;将代码段和数据段的地址设为0x10
;lss传送目标指针,将目标指针内容送入
;LSS DI,string ;把段地址:偏移地址存到SS:DI.
.text
startup_32:
movl $0x10,%eax
mov %ax,%ds
# mov %ax,%es
lss init_stack,%esp;将init_stack+4送入ss,并将init_stack地址送入esp
# setup base fields of descriptors.;设置基本描述符域
call setup_idt
call setup_gdt;在完成两个设置程序的调用之后就重置所有段寄存器
movl $0x10,%eax # reload all the segment registers
mov %ax,%ds # after changing gdt.
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss init_stack,%esp
# setup up timer 8253 chip.;设置计时器芯片8523
movb $0x36, %al
movl $0x43, %edx
outb %al, %dx #向43端口写入36
movl $11930, %eax # timer frequency 100 HZ
movl $0x40, %edx
outb %al, %dx #向40端口写入11930
movb %ah, %al
outb %al, %dx
# setup timer & system call interrupt descriptors.;
movl $0x00080000, %eax
movw $timer_interrupt, %ax;中断
movw $0x8E00, %dx
movl $0x08, %ecx # The PC default timer int.
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
movw $system_interrupt, %ax
movw $0xef00, %dx
movl $0x80, %ecx
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
# unmask the timer interrupt.
# movl $0x21, %edx
# inb %dx, %al
# andb $0xfe, %al
# outb %al, %dx
# Move to user mode (task 0)
pushfl
andl $0xffffbfff, (%esp)
popfl
movl $TSS0_SEL, %eax
ltr %ax
movl $LDT0_SEL, %eax
lldt %ax
movl $0, current
sti
pushl $0x17
pushl $init_stack
pushfl
pushl $0x0f
pushl $task0
iret
/****************************************/
setup_gdt: /****************************将lgdt_opcode的入口地址装入GDTR寄存器
lgdt lgdt_opcode
ret
将中断描述符表idt 设置成具有256 个项,并都指向ignore_int 中断门。然后加载中断* 描述符表寄存器(用lidt 指令)。真正实用的中断门以后再安装。当我们在其它地方认为一切
* 都正常时再开启中断。该子程序将会被页表覆盖掉。
*/
# 中断描述符表中的项虽然也是8 字节组成,但其格式与全局表中的不同,被称为门描述符
# (Gate Descriptor)。它的0-1,6-7 字节是偏移量,2-3 字节是选择符,4-5 字节是一些标志。setup_idt:
lea ignore_int,%edx
movl $0x00080000,%eax
movw %dx,%ax /* selector = 0x0008 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea idt,%edi
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
movl %edx,4(%edi)/////因为idt 有256项故而这里需要对其每个都加载门描述fu
addl $8,%edi
dec %ecx
jne rp_sidt
lidt lidt_opcode/********************将lidt_opcode的入口地址装入LDTR寄存器
ret
# -----------------------------------
write_char:
push %gs
pushl %ebx
# pushl %eax
mov $SCRN_SEL, %ebx
mov %bx, %gs
movl scr_loc, %bx
shl $1, %ebx
movb %al, %gs:(%ebx)
shr $1, %ebx
incl %ebx
cmpl $2000, %ebx
jb 1f