在实模式下设置各种参数,然后跳到保护模式,再在屏幕中央打出一串红色字符。实模式执行的第一步是在物理地址为0x200处设置一个坑,调试的时候就可以在物理地址为0x200处设置一个断点。
protect.asm
1 ;******************************************************************
2 ;文件名称: protect.asm
3 ;编译方法: nasm protect.asm -o protect.com
4 ;编译说明:编译成DOS专用可执行文件,可在DOS下运行。
5 ;主要功能: 从实模式进入到保护模式代码模板。
6 ;建立时间: 2011-10-07
7 ;******************************************************************
8
9 %include "protect.inc" ;*********常量及宏
10
11 org 0100h
12 jmp LABEL_BEGIN
13
14 ;**********************************************************************
15 ;全局描述符及选择子
16 ;**********************************************************************
17 [SECTION .gdt] ;********全局描述符
18 ; 段基址 段界限 属性
19 LABEL_GDT: Descriptor 0, 0, 0
20 LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA+DA_32
21 LABEL_DESC_DATA: Descriptor 0, DataLen-1, DA_DRW
22 LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32
23 LABEL_DESC_VIDEO: Descriptor 0b8000h, 0ffffh, DA_DRW+DA_DPL3
24
25 GdtLen equ $-LABEL_GDT ;*********GDT长度
26 GdtPtr dw GdtLen-1 ;*********GDT界限
27 dd 0 ;*********GDT基地址
28
29 ; ******GDT选择子
30 SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
31 SelectorData equ LABEL_DESC_DATA - LABEL_GDT
32 SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
33 SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
34
35 ;**********************************************************************
36 ;End of 全局描述符
37 ;**********************************************************************
38
39 ;**********************************************************************
40 ;全局堆栈
41 ;**********************************************************************
42 [SECTION .gs]
43 ALIGN 32
44 [BITS 32]
45 LABEL_STACK:
46 times 512 db 0
47 TopOfStack equ $ - LABEL_STACK - 1
48 ;**********************************************************************
49 ;End of 全局堆栈
50 ;**********************************************************************
51
52 ;**********************************************************************
53 ;数据段
54 ;**********************************************************************
55 [SECTION .data]
56 ALIGN 32
57 [BITS 32]
58 LABEL_DATA:
59 ;**********************字符串*********************
60 PMMessage: db "In Protect Mode now . ^_^",0
61 OffsetPMMessage equ PMMessage - $$
62 StrTest: db "ABCDEFG",0
63 OffsetStrTest equ StrTest - $$
64 DataLen equ $ - LABEL_DATA
65 ;**********************************************************************
66 ;End of 数据段
67 ;**********************************************************************
68
69
70 ;**********************************************************************
71 ;16位实模式代码段
72 ;**********************************************************************
73 [SECTION .s16]
74 [BITS 16]
75 Hoot: ;坑的入口点
76 mov ax,01h
77 mov ax,02h
78 GoBack:
79 jmp 0:Back
80 HootLen equ $ - Hoot
81
82 LABEL_BEGIN:
83
84 ;在地址为0x200处设置坑用来设置断点
85 mov ax,cs
86 mov [GoBack + 3],ax
87 mov ds,ax
88 mov si,Hoot
89 mov ax,0
90 mov es,ax
91 mov di,200h
92 mov cx,HootLen
93 rep movsb
94 jmp 0:200h
95
96 Back:
97 mov ax,cs
98 mov ds,ax
99 mov es,ax
100 mov ss,ax
101 mov sp,0100h
102
103 ;修正全局堆栈描述符的基地址
104 ResetDescBaseAddr LABEL_DESC_STACK,LABEL_STACK
105 ;修正数据段描述符的基地址
106 ResetDescBaseAddr LABEL_DESC_DATA,LABEL_DATA
107 ;修正32位代码段描述符的基地址
108 ResetDescBaseAddr LABEL_DESC_CODE32,LABEL_SEG_CODE32
109
110 ;为加载GDTR作准备
111 xor eax,eax
112 mov ax,ds
113 shl eax,4
114 add eax,LABEL_GDT
115 mov dword [GdtPtr+2],eax
116
117 ;加载GDTR
118 lgdt [GdtPtr]
119
120 ;关中断
121 cli
122
123 ;打开地址线
124 in al,92h
125 or al,00000010b
126 out 92h,al
127
128 ;开启保护模式
129 mov eax,cr0
130 or eax,1
131 mov cr0,eax
132
133 ;真正进入保护模式
134 jmp dword SelectorCode32:0
135
136 ;**********************************************************************
137 ;End of 16位实模式代码段
138 ;**********************************************************************
139
140 ;**********************************************************************
141 ;32位保护模式代码段
142 ;**********************************************************************
143 [SECTION .s32];*************32位代码段,由实模式跳入
144 [BITS 32]
145 LABEL_SEG_CODE32:
146
147 mov ax,SelectorData
148 mov ds,ax
149 mov ax,SelectorVideo
150 mov gs,ax
151
152 mov ax,SelectorStack
153 mov ss,ax
154 mov esp,TopOfStack
155
156 ;显示一个字符串
157 mov ah,0ch ;******黑底红字
158 xor esi,esi
159 xor edi,edi
160 mov esi,OffsetPMMessage ;***字符串基地址
161 mov edi,(80*10+0)*2 ;******第10行第0列
162 cld ;******正向
163 .1:
164 lodsb
165 test al,al
166 jz .2
167 mov [gs:edi],ax
168 add edi,2
169 jmp .1
170 .2: ;*****************显示完毕
171
172 call DispReturn
173 jmp $
174
175
176 DispReturn:
177 push eax
178 push ebx
179 mov eax,edi
180 mov bl,160
181 div bl
182 and eax,0ffh
183 inc eax
184 mov bl,160
185 mul bl
186 mov edi,eax
187 pop ebx
188 pop eax
189 ret
190 SegCode32Len equ $-LABEL_SEG_CODE32
191 ;**********************************************************************
192 ;End of 32位保护模式代码段
193 ;**********************************************************************
所需要的头文件protect.inc,有些没有用到,但考虑到通用性,放在里面也没事。
1 ;----------------------------------------------------------------------------
2 ; 描述符类型值说明
3 ; 其中:
4 ; DA_ : Descriptor Attribute
5 ; D : 数据段
6 ; C : 代码段
7 ; S : 系统段
8 ; R : 只读
9 ; RW : 读写
10 ; A : 已访问
11 ; 其它 : 可按照字面意思理解
12 ;----------------------------------------------------------------------------
13 DA_32 EQU 4000h ; 32 位段
14
15 DA_DPL0 EQU 00h ; DPL = 0
16 DA_DPL1 EQU 20h ; DPL = 1
17 DA_DPL2 EQU 40h ; DPL = 2
18 DA_DPL3 EQU 60h ; DPL = 3
19 ;----------------------------------------------------------------------------
20 ; 存储段描述符类型值说明
21 ;----------------------------------------------------------------------------
22 DA_DR EQU 90h ; 存在的只读数据段类型值
23 DA_DRW EQU 92h ; 存在的可读写数据段属性值
24 DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值
25 DA_C EQU 98h ; 存在的只执行代码段属性值
26 DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
27 DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值
28 DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值
29 ;----------------------------------------------------------------------------
30 ; 系统段描述符类型值说明
31 ;----------------------------------------------------------------------------
32 DA_LDT EQU 82h ; 局部描述符表段类型值
33 DA_TaskGate EQU 85h ; 任务门类型值
34 DA_386TSS EQU 89h ; 可用 386 任务状态段类型值
35 DA_386CGate EQU 8Ch ; 386 调用门类型值
36 DA_386IGate EQU 8Eh ; 386 中断门类型值
37 DA_386TGate EQU 8Fh ; 386 陷阱门类型值
38 ;----------------------------------------------------------------------------
39
40
41 ; 选择子图示:
42 ; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
43 ; ┃15┃14┃13┃12┃11┃10┃9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
44 ; ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
45 ; ┃ 描述符索引 ┃ TI ┃ RPL ┃
46 ; ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
47 ;
48 ; RPL(Requested Privilege Level): 请求特权级,用于特权检查。
49 ;
50 ; TI(Table Indicator): 引用描述符表指示位
51 ; TI=0 指示从全局描述符表GDT中读取描述符;
52 ; TI=1 指示从局部描述符表LDT中读取描述符。
53 ;
54
55 ;----------------------------------------------------------------------------
56 ; 选择子类型值说明
57 ; 其中:
58 ; SA_ : Selector Attribute
59
60 SA_RPL0 EQU 0 ; ┓
61 SA_RPL1 EQU 1 ; ┣ RPL
62 SA_RPL2 EQU 2 ; ┃
63 SA_RPL3 EQU 3 ; ┛
64
65 SA_TIG EQU 0 ; ┓TI
66 SA_TIL EQU 4 ; ┛
67 ;----------------------------------------------------------------------------
68
69
70
71
72
73 ; 宏 ------------------------------------------------------------------------------------------------------
74 ;
75 ; 描述符
76 ; usage: Descriptor Base, Limit, Attr
77 ; Base: dd
78 ; Limit: dd (low 20 bits available)
79 ; Attr: dw (lower 4 bits of higher byte are always 0)
80 %macro Descriptor 3
81 dw %2 & 0FFFFh ; 段界限 1 (2 字节)
82 dw %1 & 0FFFFh ; 段基址 1 (2 字节)
83 db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
84 dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
85 db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
86 %endmacro ; 共 8 字节
87 ;
88 ; 门
89 ; usage: Gate Selector, Offset, DCount, Attr
90 ; Selector: dw
91 ; Offset: dd
92 ; DCount: db
93 ; Attr: db
94 %macro Gate 4
95 dw (%2 & 0FFFFh) ; 偏移 1 (2 字节)
96 dw %1 ; 选择子 (2 字节)
97 dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节)
98 dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节)
99 %endmacro ; 共 8 字节
100
101
102 ;修正全局描述符的基地址
103 ;usage: ResetDescBaseAddr Descriptor, BaseAddr
104 ; Discriptor:全局描述符
105 ; BaseAddr :描述符所对应段的基地址
106 %macro ResetDescBaseAddr 2
107 xor eax,eax
108 mov ax,cs
109 shl eax,4
110 add eax,%2
111 mov word [%1+2],ax
112 shr eax,16
113 mov byte [%1+4],al
114 mov byte [%1+7],ah
115 %endmacro
参考:于渊 著 《orange's 一个操作系统的实现》
。