linux内核设计的艺术--从16位转向32位

上一篇讲到了将kernel模块加载到了内存的0x10000-0x10000+120KB处,接下来,将会执行setup.s中的代码了。


首先,setup要获取一系列系统硬件信息

mov	ax,#INITSEG	
mov	ds,ax           //设置段地址
mov	ah,#0x03	
xor	bh,bh
int	0x10		//调用0x10中断获取屏幕光标位置
mov	[0],dx		//将屏幕光标保存至0x90000处
//调用0x15中断,获取内存信息保存至0x90002
mov ah,#0x88 
int 0x15mov [2],ax
//调用0x10中断,获取显卡信息保存至0x90004 - 0x90006
mov ah,#0x0f
int 0x10
mov [4],bx 
mov [6],ax
//调用0x10中断,获取VGA/EGA配置保存至0x90008 - 0x900012
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
//获取hd0信息
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb
//获取hd1信息
mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb
//检查是否存在hd1
mov ax,#0x01500
mov dl,#0x81
int 0x13
jc no_disk1
cmp ah,#3
je is_disk1
no_disk1:mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
is_disk1:

 
 

接下来为了方便进行内核的地址映射,将system模块从0x10000处移动至0x00000处

do_move:
	mov	es,ax		//指定目标段基址
	add	ax,#0x1000
	cmp	ax,#0x9000
	jz	end_move
	mov	ds,ax		//指定源段基址
	sub	di,di
	sub	si,si
	mov 	cx,#0x8000
	rep
	movsw
	jmp	do_move

在移动完成之后,我们需要为32位地址重新建立寻址方式,32位寻址采用段描述符的方式,所以要新建一个GDT(全局描述表),以及GDTR(GDT基地址寄存器),IDT(中断描述表),IDTR(IDT基地址寄存器)

end_move:
	mov	ax,#SETUPSEG	
	mov	ds,ax
	lidt	idt_48		
	lgdt	gdt_48		


然后就是打开A20寄存器,就可以实现32位寻址


	call	empty_8042
	mov	al,#0xD1		
	out	#0x64,al
	call	empty_8042
	mov	al,#0xDF		
	out	#0x60,al
	call	empty_8042



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值