效果
![](https://i-blog.csdnimg.cn/blog_migrate/eee2e2ef906b1f2b45e792a0480b2dc3.png#pic_center)
代码
;栈段与栈指针 0x07c00 --> 0x07a00 由高地址 到 低地址
mov ax,0x07a0
mov ss,ax
mov sp,0x7c00
;--------------------------------------------------------------------------------
;计算gdt的逻辑地址
mov dx,[cs:gdt_base+0x7c00+2]
mov ax,[cs:gdt_base+0x7c00]
mov bx,0x10
div bx ;dx存商,ax存余
mov ds,ax ;段地址
mov bx,dx ;偏移地址
gdt_sta:
;创建0号描述符,空描述符(处理器要求)
mov dword [bx],0x0
mov dword [bx+0x04],0x0
add bx,0x08
;创建1号描述符,代码段描述符
mov dword [bx],0x7c0001ff ;线性基地址:0x00007c00
mov dword [bx+0x04],0x00409800 ;段界限:0x001ff
add bx,0x08
;创建2号描述符,数据段描述符
mov dword [bx],0x8000ffff ;线性基地址:0x000B8000
mov dword [bx+0x04],0x0040920b ;段界限:0x0ffff
add bx,0x08
;创建3号描述符,栈段段描述符
mov dword [bx],0x00007a00 ;线性基地址:0x00000000
mov dword [bx+0x04],0x00409600 ;段界限:0x07a00
gdt_end:
;初始化gdtr,填入gdt表字节大小
mov word [cs:gdt_size++0x7c00],gdt_end-gdt_sta-1
lgdt [cs:gdt_size++0x7c00]
;--------------------------------------------------------------------------------
;准备进入32位保护模式
in al,0x92 ;南桥芯片的端口
or al,0000_0010B ;二进制写法,下划线增加可读性
out 0x92,al ;打开地址线A20(历史遗留问题)
;详细信息:翻看P193
cli ;此时中断向量表未建立(32为保护模式下)
;禁止中断,防止出错
mov eax,cr0
or eax,0x1
mov cr0,eax ;设置PE位,打开32位保护模式
;进入32保护模式
jmp 0000000000001_000B:flush ;13位段选择子,3位属性
;清空流水线
[bits 32] ;进入32保护模式
;--------------------------------------------------------------------------------
flush:
;数据段加载
mov cx,0000000000010_000B ;选择子0x2
mov ds,cx
;以下在屏幕上显示"Protect mode OK."
mov byte [0x00],'P'
mov byte [0x02],'r'
mov byte [0x04],'o'
mov byte [0x06],'t'
mov byte [0x08],'e'
mov byte [0x0a],'c'
mov byte [0x0c],'t'
mov byte [0x0e],' '
mov byte [0x10],'m'
mov byte [0x12],'o'
mov byte [0x14],'d'
mov byte [0x16],'e'
mov byte [0x18],' '
mov byte [0x1a],'O'
mov byte [0x1c],'K'
;堆栈段加载
mov cx,0000000000011_000B ;选择子0x3
mov ss,cx
mov esp,0x7c00
;验证堆指针esp,每push/pop一次是否是加/减4
mov ebp,esp ;保存esp
push byte '.'
sub ebp,4
cmp ebp,esp ;相等则停机,不相等则显示.
jnz exit
pop eax
mov [0x1e],al
exit:
hlt ;停机指令
;--------------------------------------------------------------------------------
gdt_size dw 0
gdt_base dd 0x00007e00
times 510-($-$$) db 0
db 0x55,0xAA