跟视频有细微的不同,注释有些不一样
代码:
;计算GDT所在的逻辑段地址,结果在eax中
mov eax, [cs:pgdt+0x7c00+0x02]
xor edx, edx
mov ebx, 16
div ebx
mov ds, eax ;ds存GDT的段地址
mov ebx, edx ;ebx存GDT的偏移地址
;一个段描述符占用8个字节的空间
;创建#0描述符,这是空描述符,这是处理器的要求
mov dword [ebx+0x00], 0x00_00_00_00
mov dword [ebx+0x04], 0x00_00_00_00
;创建#1数据段描述符,段的大小为4GB
mov dword [ebx+0x08], 0x0000ffff ;基地址为0x00_00_00_00,向上扩展
mov dword [ebx+0x0c], 0x00cf9200 ;段界限为0xff_ff_f,粒度为4KB,数据段描述符
;创建#2保护模式下初始代码段描述符
mov dword [ebx+0x10], 0x7c0001ff ;limit(段限长/段界限): 1FF base(段基地址): 7C00 TYPE(段类型): 代码段
mov dword [ebx+0x14], 0x00409800
;创建#3数据段描述符,实际用做第一个栈段
mov dword [ebx+0x18], 0x6c0007ff
mov dword [ebx+0x1c], 0x00409200
;创建#4数据段描述符,实际用作第二个栈段
mov dword [ebx+0x20], 0x7c00fffe
mov dword [ebx+0x24], 0x00cf9600
;初始化描述符表寄存器GDTR
mov word [cs:pgdt+0x7c00], 39
lgdt [cs:pgdt+0x7c00]
in al, 0x92
or al, 0000_0010B
out 0x92, al
cli
mov eax, cr0
or eax, 1
mov cr0, eax
;以下进入保护模式
jmp 0x0010:flush
[bits 32]
flush:
;ds设置为#1数据段
mov eax, 0x0008 ;索引1,在GDT中,特权级0级
mov ds, eax
;ss设置为第一个栈段
mov eax, 0x0018 ;索引3,在GDT中,特权级0级
mov ss, eax
mov esp, 0x800
push dword 0x072e074d ;字符'M'、'.'及其显示属性
push dword 0x072e0750 ;字符'P'、'.'及其显示属性
pop dword [0x0b8000] ;写入显存 字符'P'、'.'及其显示属性
pop dword [0x0b8004] ;写入显存 字符'M'、'.'及其显示属性
mov eax, 0x0020 ;索引4,在GDT中,特权级0级
mov ss, eax
mov esp, 0
push dword 0x076b076f ;字符'o'、'k'及其显示属性
push dword 0x07200720 ;两个空白字符及其显示属性
pop dword [0x0b8008] ;写入显存 两个空白字符及其显示属性
pop dword [0x0b800c] ;写入显存 字符'o'、'k'及其显示属性
hlt ;停机指令
;----------------------------------------------------------------------------------------------
pgdt dw 0
dd 0x00007e00 ;GDT的物理地址
;----------------------------------------------------------------------------------------------
times 510-($-$$) db 0
db 0x55, 0xaa