linux 0.11时钟初始化,linux-0.11 初始化---Head.s

# linux/boot/head.s

#  (C) 1991

Linus Torvalds

#  head.s contains the 32-bit startup

code.

# NOTE!!! Startup happens at absolute address 0x00000000,

which is also where

# the page directory will exist. The startup code will be

overwritten by

#the page directory.

.text

.globl _idt,_gdt,_pg_dir,_tmp_floppy_area

_pg_dir:

startup_32:

movl $0x10,% eax

mov % ax,% ds

mov % ax,% es

mov % ax,% fs

mov % ax,% gs

lss _stack_start,% esp #_stack_start-->ss:esp 设置系统堆栈

call setup_idt #将中断描述符表idt设置成具有256个项,并都指向ignore

int中断门,然后

#加载中断描述符表寄存器(用lidt指令)

call setup_gdt #设置全局描述符表寄存器

movl $0x10,% eax # reload all the segment registers

mov % ax,% ds # after changing gdt. CS was already

mov % ax,% es # reloaded in 'setup_gdt'

mov % ax,% fs

mov % ax,% gs

lss _stack_start,% esp

xorl % eax,% eax

1: incl % eax # check that A20 really IS enabled

movl % eax,0x000000 # loop forever if it isn't

cmpl % eax,0x100000

je 1b

movl % cr0,% eax # check math chip

andl $0x80000011,% eax # Save PG,PE,ET

orl $2,% eax # set MP

movl % eax,% cr0

call check_x87

jmp after_page_tables

#finit

向协处理器发出初始化命令,它会把协处理器置于一个未受以前操作影响的已知状态,设置其控制字为默认值、清除状态字和所有浮点栈式寄存器。非等待形式的这条指令(fninit)还会让协处理器终止执行当前正在执行的任何先前的算术操作。fstsw

指令取协处理器的状态字。如果系统中存在协处理器的话,那么在执行了fninit指令后其状态字低字节肯定为0。

check_x87:

fninit

fstsw % ax

cmpb $0,% al

je 1f #check 是否含有协处理器

movl % cr0,% eax

xorl $6,% eax #reset MP EM 位

movl % eax,% cr0

ret

.align 2

1: .byte 0xDB,0xE4 # fsetpm for 287, ignored

by 387

ret

setup_idt:

lea ignore_int,% edx

movl $0x00080000,% eax

movw % dx,% ax

movw $0x8E00,% dx

lea _idt,% edi

mov $256,% ecx

rp_sidt:

movl % eax,(% edi)

movl % edx,4(% edi)

addl $8,% edi

dec % ecx

jne rp_sidt

lidt idt_descr

ret

setup_gdt:

lgdt gdt_descr

ret

.org 0x1000

pg0:

.org 0x2000

pg1:

.org 0x3000

pg2:

.org 0x4000

pg3:

.org 0x5000

_tmp_floppy_area:

.fill 1024,1,0

after_page_tables:

pushl $0 # These are the parameters to main :-)

pushl $0

pushl $0

pushl $L6 # return address for main, if it decides to.

pushl $_main

jmp setup_paging

L6:

jmp L6 # main should never return here, but

# just in case, we know what happens.

int_msg:

.asciz "Unknown interrupt\n\r"

.align 2

ignore_int:

pushl % eax

pushl % ecx

pushl % edx

push % ds

push % es

push % fs

movl $0x10,% eax

mov % ax,% ds

mov % ax,% es

mov % ax,% fs

pushl $int_msg

call _printk

popl % eax

pop % fs

pop % es

pop % ds

popl % edx

popl % ecx

popl % eax

iret

#将

.align 2

setup_paging:

movl $1024*5,% ecx #5 pages : pg_dir+4 page

tables

xorl % eax,% eax # pg_dir is at

0x000

xorl % edi,% edi

cld;rep;stosl #把eax中的内容存放到es:edi指定内存中,edi+4, 清零前5页内存

movl $ pg0+7,_pg_dir #set present bit/user r/w

在第一个页表中

movl pg1+7,_pg_dir+4 #set

present bit/user r/w  在第二个页表中

movl $pg2+7,_pg_dir+8

movl $pg3+7,_pg_dir+12

movl $pg3+4092,% edi #es:edi -->指向最后一页的最后一项

movl $0xfff007,% eax

#最后一个页表的最后一项里面指定的物理内存页面地址是0xfff000,7是属性

std #方向位值位,edi-4

1: stosl # fill pages backwards - more

efficient :-)

subl $0x1000,% eax # 每设置好一项,物理地址减0x1000(4K)

jge 1b

xorl % eax,% eax # pg_dir is at

0x0000

movl % eax,% cr3 # cr3 : page directory

start

movl % cr0,% eax

orl $0x80000000,% eax

movl % eax,% cr0 #set paging (PG)

bit

ret #this also flushes

prefetch-queue ,改变分页标志后需要更新。跳转到main

#执行,出栈到/init/main.c中运行

.align 2

.word 0

idt_descr:

.word 256*8-1 # idt contains 256 entries

.long _idt

.align 2

.word 0

gdt_descr:

.word 256*8-1 # so does gdt (not that that's any

.long _gdt # magic number, but it works for me :^)

.align 3

_idt: .fill 256,8,0 # idt is uninitialized

_gdt: .quad 0x0000000000000000

.quad 0x00c09a0000000fff

.quad 0x00c0920000000fff

.quad 0x0000000000000000

.fill 252,8,0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值