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

来源:互联网 发布:怎么看淘宝收货时间 编辑:程序博客网 时间:2024/06/06 20:52

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


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

movax,#INITSEGmovds,ax           //设置段地址movah,#0x03xorbh,bhint0x10//调用0x10中断获取屏幕光标位置mov[0],dx//将屏幕光标保存至0x90000处//调用0x15中断,获取内存信息保存至0x90002mov ah,#0x88 int 0x15mov [2],ax//调用0x10中断,获取显卡信息保存至0x90004 - 0x90006mov ah,#0x0fint 0x10mov [4],bx mov [6],ax//调用0x10中断,获取VGA/EGA配置保存至0x90008 - 0x900012mov ah,#0x12mov bl,#0x10int 0x10mov [8],axmov [10],bxmov [12],cx//获取hd0信息mov ax,#0x0000mov ds,axlds si,[4*0x41]mov ax,#INITSEGmov es,axmov di,#0x0080mov cx,#0x10repmovsb//获取hd1信息mov ax,#0x0000mov ds,axlds si,[4*0x46]mov ax,#INITSEGmov es,axmov di,#0x0090mov cx,#0x10repmovsb//检查是否存在hd1mov ax,#0x01500mov dl,#0x81int 0x13jc no_disk1cmp ah,#3je is_disk1no_disk1:mov ax,#INITSEGmov es,axmov di,#0x0090mov cx,#0x10mov ax,#0x00repstosbis_disk1:

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

do_move:moves,ax//指定目标段基址addax,#0x1000cmpax,#0x9000jzend_movemovds,ax//指定源段基址subdi,disubsi,simov cx,#0x8000repmovswjmpdo_move

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

end_move:movax,#SETUPSEGmovds,axlidtidt_48lgdtgdt_48


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


callempty_8042moval,#0xD1out#0x64,alcallempty_8042moval,#0xDFout#0x60,alcallempty_8042



2 0