.globl start
.include "kernel.inc"
include the above file
.code16
start:
jmp code
gdt:
.quad 0x0000000000000000 # null descriptor
.quad 0x00cf9a000000ffff # cs
.quad 0x00cf92000000ffff # ds
.quad 0x0000000000000000 # reserved for further use
.quad 0x0000000000000000 # reserved for further use
gdt_48:
.word .-gdt-1 # 当前地址减gdt地址减1得到GDT的长度 # 知道是长度这个属性了,这样子计算的,那个小点,估计代表的是当前地址,看的时候要注意
.long GDT_ADDR
code:
xorw %ax, %ax
movw %ax, %ds # 数据段 = 0x0000
movw %ax, %ss # 堆栈段 = 0x0000
movw $0x1000,%sp # 保护模式前用的堆栈,不要让他覆盖到7c00处的引导程序即可
movw $0x1000,%ax #ax=0x1000
movw %ax, %es #es=ax
xorw %bx, %bx # es:bx 加载内核的目标地址
movw $KERNEL_SECT,%cx #cx= KERNEL_SECT, 72 # 内核大小,单位是,36k对于现在来说已经足够了
movw $1, %si # 0,跳过去,所以是1
rd_kern:
call read_sect # 入口参数:si是起始扇区数,es:bx是指定内存地址,从哪儿读到内存es:bx处的呢
addw $512, %bx #增量为512,一个扇区的大小
incw %si #si扇区的个数
loop rd_kern
cli # 就要进入保护模式了,所以关掉实模式下的中断
movw $0x1000,%ax #ax=0x1000
movw %ax, %ds #ds=ax
movw $0x0000,%ax #ax=0x0000
movw %ax, %es #es=ax
xorw %si, %si #si=0
xorw %di, %di #di=0
movw $512>>2,%cx #cx=128??????,控制传输的次数明白为啥是128了,因为movsl这个指令一次传送的是四个字节(双字)
rep
movsl #将DS:SI这段地址的N个字节复制到ES:DI指向的地址,恩,很有感觉了
xorw %ax, %ax
movw %ax, %ds # 复位 ds 为 0x0000
movw $GDT_ADDR>>4,%ax # (0x80000 + 256 * 8) >> 2 ####IDT_ADDR= 0x80000
movw $gdt, %si #我感觉gdt标号在编译好的目标中应该相当于一个偏移的感觉
xorw %di, %di # 从ds:si 拷贝到 es:di中
movw $GDT_SIZE>>2,%cx # 拷贝数据段中的gdt到指定地址
rep
movsl
# * 读60h端口,读output buffer
# * 写60h端口,写input buffer
# * 读64h端口,读Status Register
#seta20.1: inb $0x64,%al # Get status 读状态寄存器 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
enable_a20:
inb $0x64, %al #inbyte(猜测的),读64h端口状态
testb $0x2, %al #看看是否繁忙
jnz enable_a20
movb $0xbf, %al
outb %al, $0x64 #貌似为什么不是60端口呢???,难道状态口和读写口都不分的吗
# 进入保护模式
movl %cr0, %eax
orl $0x1, %eax
movl %eax, %cr0 # 使能CR0 控制寄存器中的PE位(即第0位)
ljmp $CODE_SEL, $0x0
# 输出 es:bx 读取扇区到这个内存地址
read_sect:
pushw %ax
pushw %cx
pushw %dx
pushw %bx
movw %si, %ax
xorw %dx, %dx
movw $18, %bx # 对于1.44M软盘:每磁道18扇区
divw %bx
incw %dx
movb %dl, %cl # cl = 扇区号
xorw %dx, %dx
movw $2, %bx # 每磁道2磁头
divw %bx
movb %dl, %dh # 磁头
xorb %dl, %dl # 软驱号
movb %al, %ch # 柱面
rp_read:
movb $0x1, %al # 读1个扇区
movb $0x2, %ah
int $0x13
jc rp_read
popw %dx
popw %cx
popw %ax
ret