Linux-0.11 实模式到保护模式

来源:互联网 发布:云计算的分类有哪些 编辑:程序博客网 时间:2024/05/18 02:50

bootsect部分已经执行完成,程序也跳转到setup部分:

start:! ok, the read went well so we get current cursor position and save it for! posterity.movax,#INITSEG! this is done in bootsect already, but...movds,axmovah,#0x03! read cursor posxorbh,bhint0x10! save it in known place, con_init fetchesmov[0],dx! it from 0x90000.

首先读取光标的位置,然后存储在内存0x90000地址处,从前面来看,bootsect部分代码存储在内存地址0x90000处,但是现在已经没有什么用了,使用了这段内存来保存一些参数(并没有开辟新的内存空间,重复利用该段内存空间)。


! Get memory size (extended mem, kB)movah,#0x88int0x15mov[2],ax

然后调用int 15h中断例程获取内存大小,单位kB。


! Get video-card data:movah,#0x0fint0x10mov[4],bx! bh = display pagemov[6],ax! al = video mode, ah = window width

读取显卡数据。


! check for EGA/VGA and some config parametersmovah,#0x12movbl,#0x10int0x10mov[8],axmov[10],bxmov[12],cx

检查显示方式和获取配置参数。


! Get hd0 datamovax,#0x0000movds,axldssi,[4*0x41]movax,#INITSEGmoves,axmovdi,#0x0080movcx,#0x10repmovsb

将第一个硬盘参数表复制到内存0x90080地址处,大小16个字节,存储在0x90080地址处。


! Get hd1 datamovax,#0x0000movds,axldssi,[4*0x46]movax,#INITSEGmoves,axmovdi,#0x0090movcx,#0x10repmovsb

将第二个硬盘参数表复制到内存0x90090地址处,大小16个字节,存储在0x90090地址处。


! Check that there IS a hd1 :-)movax,#0x01500movdl,#0x81int0x13jcno_disk1cmpah,#3jeis_disk1no_disk1:movax,#INITSEGmoves,axmovdi,#0x0090movcx,#0x10movax,#0x00repstosbis_disk1:

检查是否存在第二个硬盘(hd1),如果不存在,则将0x90090地址处的硬盘参数表清零。


! now we want to move to protected mode ...cli! no interrupts allowed !

即将进入保护模式下工作,首先是关闭中断。


! first we move the system to it's rightful placemovax,#0x0000cld! 'direction'=0, movs moves forwarddo_move:moves,ax! destination segmentaddax,#0x1000cmpax,#0x9000jzend_movemovds,ax! source segmentsubdi,disubsi,simov cx,#0x8000repmovswjmpdo_move

然后是将system部分从内存0x10000地址处移动到内存0x00000处,移动大小是0x80000,即512kB大小(即system部分不能超过512kB)。


! then we load the segment descriptorsend_move:movax,#SETUPSEG! right, forgot this at first. didn't work :-)movds,axlidtidt_48! load idt with 0,0lgdtgdt_48! load gdt with whatever appropriate

用于加载全局描述符(GDT)表和中断描述符表(IDT)。


! that was painless, now we enable A20        call    empty_8042mov     al,#0xD1                ! command writeout     #0x64,alcall    empty_8042mov     al,#0xDF                ! A20 onout     #0x60,alcall    empty_8042

empty_8042子函数用于测试8042控制器输入缓冲区是否为空,只有为空的情况下才能对其进行写命令操作。

! This routine checks that the keyboard command queue is empty! No timeout is used - if this hangs there is something wrong with! the machine, and we probably couldn't proceed anyway.empty_8042:        .word   0x00eb,0x00ebin      al,#0x64        ! 8042 status porttest    al,#2           ! is input buffer full?jnz     empty_8042      ! yes - loopret

那么前面用于使能A20地址总线,寻址空间也就从1MB变成4GB。


! well, that went ok, I hope. Now we have to reprogram the interrupts :-(! we put them right after the intel-reserved hardware interrupts, at! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really! messed this up with the original PC, and they haven't been able to! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,! which is used for the internal hardware interrupts as well. We just! have to reprogram the 8259's, and it isn't fun.        mov     al,#0x11                ! initialization sequence        out     #0x20,al                ! send it to 8259A-1        .word   0x00eb,0x00eb           ! jmp $+2, jmp $+2        out     #0xA0,al                ! and to 8259A-2        .word   0x00eb,0x00eb        mov     al,#0x20                ! start of hardware int's (0x20)        out     #0x21,al        .word   0x00eb,0x00eb        mov     al,#0x28                ! start of hardware int's 2 (0x28)        out     #0xA1,al        .word   0x00eb,0x00eb        mov     al,#0x04                ! 8259-1 is master        out     #0x21,al        .word   0x00eb,0x00eb        mov     al,#0x02                ! 8259-2 is slave        out     #0xA1,al        .word   0x00eb,0x00eb        mov     al,#0x01                ! 8086 mode for both        out     #0x21,al        .word   0x00eb,0x00eb        out     #0xA1,al        .word   0x00eb,0x00eb        mov     al,#0xFF                ! mask off all interrupts for now        out     #0x21,al        .word   0x00eb,0x00eb        out     #0xA1,al

上面这段代码用于初始化8259A中断控制器。


! well, that certainly wasn't fun :-(. Hopefully it works, and we don't! need no steenking BIOS anyway (except for the initial loading :-).! The BIOS-routine wants lots of unnecessary data, and it's less! "interesting" anyway. This is how REAL programmers do it.!! Well, now's the time to actually move into protected mode. To make! things as simple as possible, we do no register set-up or anything,! we let the gnu-compiled 32-bit programs do that. We just jump to! absolute address 0x00000, in 32-bit protected mode.mov     ax,#0x0001      ! protected mode (PE) bitlmsw    ax              ! This is it!jmpi    0,8             ! jmp offset 0 of segment 8 (cs)

最后真正的进入保护模式,跳转到0地址处,即system部分。

0 0