#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