今天学习了保护模式,依据书上的内容以及大灰狼老师的视频,终于完成自己写的保护模式。
[BITS 16] ;表示以下为段位16位
org 07c00h ;这是由于系统会将代码加载到7C00处
jmp start
gdt_table_start:
gdt_null:
dd 0h
dd 0h ;Intel 规定描述符表的第一个描述符必须为空描述符
gdt_data_addr equ $-gdt_table_start
gdt_data:
dw 07FFh ;数据段的界值,一个数据段、代码段规定为8M大小
dw 0h ;段基址的0~18位
db 0h ;段基址的19~23位
db 10010010b ;第一个1,表示P,是描述符对地址的转换是否有效,有效为1
;第二个1,表示DT,表示是系统段还是存储段,为1表示系统段
;第三个1,与0010一起表示type类型,即是可读可写的数据段还是可读可执行的代码段
;段属性的第六字节
db 11000000b ;第一个1,表示是数据段大小4G,为0则表示64K;代码段是32位,为0则表示16位
;第二个1表示段界限粒度为字节,0则表示为4K
;段属性的第七字节
db 0h ;基地址
gdt_code_addr equ $-gdt_table_start
gdt_code:
dw 07FFh ;代码段的界值,一个数据段、代码段规定为8M大小
dw 1h ;段基址的0~18位
db 80h ;段基址的19~23位
db 10011010b ;第一个1,表示P,是描述符对地址的转换是否有效,有效为1
;第二个1,表示DT,表示是系统段还是存储段,为1表示系统段
;第三个1,与1010一起表示type类型,即是可读可写的数据段还是可读可执行的代码段
;段属性的第六字节
db 11000000b ;第一个1,表示是数据段大小4G,为0则表示64K
;第二个1表示代码段是32位,为0则表示16位
;段属性的第七字节
db 0h ;基地址
gdt_video_addr equ $-gdt_table_start
gdt_video:
dw 01FFh ;代码段的界值,可以为任意值
dw 8000h ;段基址的0~18位
db 0Bh ;段基址的19~23位
db 10010010b ;第一个1,表示P,是描述符对地址的转换是否有效,有效为1
;第二个1,表示DT,表示是系统段还是存储段,为1表示系统段
;第三个1,与1010一起表示type类型,即是可读可写的数据段还是可读可执行的代码段
;段属性的第六字节
db 11000000b ;第一个1,表示是数据段大小4G,为0则表示64K
;第二个1表示代码段是32位,为0则表示16位
;段属性的第七字节
db 0h ;基地址
gdt_table_end:
gdtr_addr:
dw gdt_table_end-gdt_table_start-1 ;段描述符表长度,GDTR寄存器为48位
dd gdt_table_start ;段描述符表基地址
start:
;初始化数据段描述符
xor eax , eax
mov eax , data_32
mov word [gdt_data+2] ,ax
shr eax , 16
mov byte [gdt_data+4] , al
mov byte [gdt_data+7] ,ah
;初始化代码段描述符
xor eax , eax
mov eax , code_32
mov word [gdt_code+2] ,ax
shr eax , 16
mov byte [gdt_code+4] , al
mov byte [gdt_code+7] ,ah
;关闭中断向量表,相当于删除以前的16位中断向量表,为装入32位中断向量表做准备
cli
;加载GDT描述表的大小和基地址放入gdtr寄存器
lgdt [gdtr_addr]
;打开A20地址线,以便能够访问超过1M的地址内存
in al , 92h
or al ,00000010b
out 92h , al
;打开保护模式允许
mov eax , cr0
or eax ,1
mov cr0 , eax
;跳转到保护模式下的32位地址处
jmp gdt_code_addr:0
[BITS 32]
data_32:
dd "my os!"
code_32:
mov ax , gdt_data_addr
mov ds , ax
mov ax , gdt_video_addr
mov gs ,ax
mov edi ,(80*20+30)*2 ;在屏幕第20行第30列处显示数据my os!
mov ah , 0ch ;黑底红字
mov bx ,0
mov cx ,6
s:
mov al , [ds:bx]
mov [gs:edi] , al
mov [gs:edi+1] , ah
inc bx
add edi ,2
loop s
jmp $
times 510-($-$$) db 0
dw 0aa55h