lab1_練習3_bootasm.S(設置gdt 進入保護模式)

#include <asm.h>

# with %cs=0 %ip=7c00.

.set PROT_MODE_CSEG,        0x8                     # 內核代碼段選擇子 cpl=0 index = 1
.set PROT_MODE_DSEG,        0x10                    # 內核數據段選擇子 rpl=0 index = 2
.set CR0_PE_ON,             0x1                     # 用於對cr0置位

# start address should be 0:7c00, in real mode, the beginning address of the running bootloader
.globl start
start:
.code16                                             # Assemble for 16-bit mode
    cli                                             # Disable interrupts
    cld                                             # String operations increment

    # 設置實模式數據段寄存器  都爲0
    xorw %ax, %ax                                   # Segment number zero
    movw %ax, %ds                                   # -> Data Segment
    movw %ax, %es                                   # -> Extra Segment
    movw %ax, %ss                                   # -> Stack Segment

    # Enable A20:
    #  For backwards compatibility with the earliest PCs, physical
    #  address line 20 is tied low, so that addresses higher than
    #  1MB wrap around to zero by default. This code undoes this.
seta20.1:
    inb $0x64, %al                                  # 讀取status register 直到input buffer
(0x60和0x64)爲空
    testb $0x2, %al
    jnz seta20.1

    movb $0xd1, %al                                 # 向control register 寫入寫output port命令
    outb %al, $0x64                                 
seta20.2:
    inb $0x64, %al                                  # 讀取status register 直到input buffer
(0x60和0x64)爲空
    testb $0x2, %al
    jnz seta20.2

    movb $0xdf, %al                                 # 0xdf -> port 0x60 A20使能
    outb %al, $0x60                                 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1


    lgdt gdtdesc                                    #設置gdtr爲gdt的基地址和段限界
    movl %cr0, %eax                                 #對cr0寄存器的0bit置位
    orl $CR0_PE_ON, %eax
    movl %eax, %cr0

    # Jump to next instruction, but in 32-bit code segment.
    # Switches processor into 32-bit mode.
    ljmp $PROT_MODE_CSEG, $protcseg

.code32                                             # Assemble for 32-bit mode
protcseg:
    # 保護模式下設置段寄存器
    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

    # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00)
    #設置堆棧段地址
    movl $0x0, %ebp
    movl $start, %esp
    call bootmain

    # If bootmain returns (it shouldn't), loop.
spin:
    jmp spin

# Bootstrap GDT
.p2align 2                                          # force 4 byte alignment
gdt:
    SEG_NULLASM                                     # null seg
    SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)           # code seg for bootloader and kernel
    SEG_ASM(STA_W, 0x0, 0xffffffff)                 # data seg for bootloader and kernel


#高32位爲gdt基址 低16位爲段限界
gdtdesc:
    .word 0x17                                      # sizeof(gdt) - 1
    .long gdt                                       # address gdt

 

執行長跳轉以後, cs = 8,index = 1, base = 0,執行的下一條指令的線性地址爲0x7c32.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章