1、关中断,标记位IF设为0。设置串处理从低地址向高地址处理(SI、DI增大),即DF为0
2、相关寄存器清零,堆栈寄存器设置为0x7c00开始
xorw %ax,%ax # Segment number zero
movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment
# 设置堆栈指针, 从0x7c00 向下 ,start是该段代码的起始标号,即0x7c00
movw $start,%sp
|
3、
A20地址线:从80286开始,系统出现了一种新的机制,被称为保护模式。到了80386,保护模式得到了进一步的完善和发展,并且对于80386以后的芯片,保护模式的变化就非常小了。在保护模式下,如果A20 Gate被禁止,则可以访问的内存只能是奇数1M段,即1M,3M,5M…,也就是00000-FFFFF, 200000-2FFFFF,300000-3FFFFF…。如果A20 Gate被打开,则可以访问的内存则是连续的。而实模式要想访问1M以上的内存也要打开,所以A20 Gate无论如何都要打开的打开A20 Gate,从理论上讲,打开A20 Gate的方法是通过设置8042芯片输出端口(64h)的2nd-bit,但事实上,当你向8042芯片输出端口进行写操作的时候,在键盘缓冲区中,或许还有别的数据尚未处理,因此你必须首先处理这些数据。
seta20.1: inb $0x64,%al # 获取状态 in al,0x64
testb $0x2,%al # Busy? test al,0x02
jnz seta20.1 # Yes 占用则跳转
movb $0xd1,%al # Command: Write
outb %al,$0x64 # output port
seta20.2: inb $0x64,%al # Get status
testb $0x2,%al # Busy?
jnz seta20.2 # Yes
movb $0xdf,%al # Enable
outb %al,$0x60 # A20 ROM BASIC 入口
|
4、
装载全局描述符,并设置cr0(PE位设置为1)进入使系统进入保护模式real_to_prot: cli # 现在还不能允许中断
# 我们还没有设置中断描述符表
lgdt gdtdesc # 加载全局描述符
movl %cr0, %eax # 打开保护模式 cr0为控制寄存器,还有 cr1 cr2 cr3
orl $CR0_PE_ON, %eax #.set CR0_PE_ON,0x1
movl %eax, %cr0
|
5、接下来系统进入32位的保护模式,进行了一个关键跳转
.set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector
ljmp $PROT_MODE_CSEG, $protcseg
|
注意
PROT_MODE_CSEG为段选择子,段选择子的格式如下
所以对于PROT_MODE_CSEG定义为0x8而言,就是选择第一个代码段,也即是当前执行的代码段,同样$protcseg也即是当前代码里面的$protcset处,程序也就跳入了32位的保护模式进行运行
6、下面是一些寄存器的初始化,并跳入c代码运行
movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment
call cmain # finish the boot load from C.
|
阅读(1655) | 评论(0) | 转发(0) |