ucore lab1 任务四

来源:互联网 发布:联通网络电视破解软件 编辑:程序博客网 时间:2024/06/05 19:34

任务四:

 Bootloader如何做准备并进入保护模式的?

 

      通过查询相关指令含义总结bootasm.s的具体执行流程为:

       首先在实模式下运行---〉打开A20端口---〉加载GDTR,进入保护模式---〉调用bootmain函数

 .setPROT_MODE_CSEG,       0x8                     #kernel code segment selector

.set PROT_MODE_DSEG,        0x10                    #kernel data segment selector

.set CR0_PE_ON,             0x1                     #protected mode enable flag

 

.globl start

start:

.code16                                             #Assemble for 16-bit mode

    cli                                         //CLI可以屏蔽中断,防止运行中中断

    cld                                         //CLD使DF复位,即DF=0,串操作方向控制

 

    #Set up the important data segment registers (DS, ES, SS).                   //设置段寄存器的值

    xorw%ax, %ax                                   //使用异或指令,将ax寄存器的值设置为0

    movw%ax, %ds                                   //将ax寄存器的值移动到DS寄存器中

    movw %ax, %es                                   //同上

    movw%ax, %ss                                  

                                               //上述指令将DS,ES,SS,AS寄存器的值全部设置为0

    #Enable A20:

    #  For backwards compatibility with the earliestPCs, physical               

    #  address line 20 is tied low, so thataddresses higher than

    #  1MB wrap around to zero by default. This codeundoes this.

seta20.1:

    inb$0x64, %al      //从0x64端口读一字节数据到al寄存器中,返回i8042中状态寄存器的内容

    testb$0x2, %al    

 //将al按位与0010进行AND操作并对标志寄存器进行置位,运算结果0,ZF置1,否则置0

    jnzseta20.1      

//JNZ就是ZF不为1时跳转,到seta20.1重新开始运行,说明如果0x64中倒数第二位为0时程序才正常执行

 

    movb$0xd1, %al                     //如果完成上述操作将端口0x64的值置位0xd1,

    outb%al, $0x64

 

seta20.2:

    inb$0x64, %al                                  #Wait for not busy

    testb$0x2, %al

    jnzseta20.2                                                                 

 //同样判断键盘控制器是否繁忙

 

    movb$0xdf, %al                                 //如果不繁忙将0xdf的值传给0x60

    outb%al, $0x60

//上述代码的作用是打开A20地址线

    #Switch from real to protected mode, using a bootstrap GDT

    #and segment translation that makes virtual addresses

    #identical to physical addresses, so that the

    #effective memory map does not change during the switch.

    lgdtgdtdesc                                                                  

//通过lgdt汇编指令可以把GDTR描述符表的大小和起始位置存入gdtr寄存器中

    movl%cr0, %eax                                                               

//将CRO寄存器的内容移动到ax中

    orl$CR0_PE_ON, %eax                                                          

//通过逻辑或操作将eax寄存器的第一位置设为1。

    movl%eax, %cr0                                                               

//将CR0的最后一位设置为1,进入保护模式(!!!)

 

    #Jump to next instruction, but in 32-bit code segment.                     

    #Switches processor into 32-bit mode.

    ljmp$PROT_MODE_CSEG, $protcseg                                              

 //指令跳转由代码段选择子0x8跳到protcseg的起始位置

 

.code32                                             #Assemble for 32-bit mode

protcseg:              

    #Set up the protected-mode data segment registers                           

 //下面进入保护模式的操作

    movw$PROT_MODE_DSEG, %ax                       #Our data segment selector   

//将数据段选择子0x10赋值给ax

    movw%ax, %ds                                   #-> DS: Data Segment         

 //将数据段选择子赋值给DS

    movw%ax, %es                                   #-> ES: Extra Segment

    movw%ax, %fs                                   #-> FS

    movw%ax, %gs                                   #-> GS

    movw%ax, %ss                                   #-> SS: Stack Segment

 

    #Set up the stack pointer and call into C.                                  

    movl$0x0, %ebp                                                             

 //将bp寄存器的值设置为0x0

    movl$start, %esp                                                           

 //将sp寄存器的值设置为START标示处的地址

    callbootmain                                                               

 //调用bootmain函数

 

    # Ifbootmain returns (it shouldn't), loop.

spin:

    jmpspin                                                   

 

# Bootstrap GDT

.p2align 2                                          #force 4 byte alignment

gdt:

    SEG_NULLASM                                     # null seg                         

 //通过查找asm.h文件可知,实际此段为8个值为0的字节

    SEG_ASM(STA_X|STA_R,0x0, 0xffffffff)           # code seg forbootloader and kernel

 //此段为定义代码段

    SEG_ASM(STA_W,0x0, 0xffffffff)                 # dataseg for bootloader and kernel

 //定义数据段

 

gdtdesc:                                                                                  //此为段描述符表的地址

    .word0x17                                      #sizeof(gdt) - 1                     //大小

    .longgdt                                       #address gdt                         //起始位置

原创粉丝点击