Linux-0.01 引导代码分析-head.s

本文聚焦于Linux内核的初始引导代码head.s,它在被boot.s加载到保护模式的零地址执行后,逐步启动系统。head.s的职责包括处理编译链接,并最终调用main函数进行后续操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

head.s 通过编译链接的处理,同时被 boot.s 加载到保护模式零地址开始运行,在最后会调用 main 函数。

代码:

/*
 *  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.
 * 注意:启动程序在 0x00000000,同时这个地址也是页表的地址,在这个启动完成后,这里的程序与数据会被页表覆盖。
 */
.code32 .text
.globl idt, gdt, pg_dir, startup_32

pg_dir:
startup_32:
	movl $0x10,%eax # 已经处于32 位保护模式,$0x10 是全局描述符表项的选择符
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
	lss stack_start,%esp # 设置系统堆栈:ss,esp,stack_start 在 kernel/sched.c, 40 行
	
	call setup_idt # 设置中断描述符表
	call setup_gdt # 设置全局描述符表
	
	# 因为修改了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
	
	# 测试A20 地址线是否已经开启,如果没有开启,内核无法使用大于 1M 的内存
	# 采用的方法是向内存地址0x000000 处写入任意数值,
	# 检查 0x100000(1M) 处是否也是这个数值。
1:	incl %eax		# check that A20 really IS enabled
	movl %eax,0x000000
	cmpl %eax,0x100000
	je 1b # 向后寻找标号
	
	# CR0 : http://en.wikipedia.org/wiki/Control_register
	movl %cr0,%eax		# check math chip
	andl $0x80000011,%eax	# Save PG,ET,PE
	testl $0x10,%eax # test MP 位
	jne 1f			# ET is set - 387 is present
	orl $4,%eax		# else set emulate bit, EM 位
1:	movl %eax,%cr0
	jmp after_page_tables

/*********************************setup_idt*******************************/
/*
 *  setup_idt
 *
 *  sets up a idt with 256 entries pointing to
 *  ignore_i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值