1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
|
;============================================================================
;演示保护模式下的IO保护
;编译选项请参见 makefile TAB = 8
;============================================================================
.686p
Include pm.inc
option casemap:none
Stack_Len equ 1024 ;堆栈大小
;============================================================================
GdtSeg Segment use16 ;全局描述符表
; ;段基址 ;段界限 ;属性
Dummy: Descriptor 0, 0, 0 ;空的描述符
Normal: Descriptor 0, 0ffffh, DA_DRW ;规范段描述符
g_DataDesc: Descriptor 0, 0fffffh, DA_DRWG or DA_DPL3 ;全局4G数据段
g_IdtCode32Desc: Descriptor 0, IdtCodeSegLen-1, DA_CR or DA_32 or DA_DPL1 ;中断处理函数描述符
g_CodeTempDesc: Descriptor 0, 0ffffh, DA_C ;非一致代码段16位
g_CodeSwitchDesc: Descriptor 0, DemoCodeSegLen-1, DA_C or DA_32 ;数据段
g_VideoDesc: Descriptor 0b8000h,0ffffh, DA_DRW or DA_DPL3 ;显存段(可读写)
g_DemoTssDesc: Descriptor 0, DemoTssSegLen-1, DA_386TSS ;演示任务TSS段描述符
g_TestTssDesc: Descriptor 0, TestTssSegLen-1, DA_386TSS ;测试任务TSS段描述符
g_DemoLdtDesc: Descriptor 0, LdtDemoSegLen-1, DA_LDT ;演示任务的LDT描述符
g_TestLdtDesc: Descriptor 0, LdtTestSegLen -1, DA_LDT ;测试代码段的LDT描述符
;----------------------------------------------------------------------------
;任务门 段选择子 入口 参数个数 属性
g_TestTask: Gate g_TestTssSelector, 0, 0, DA_TaskGate ;386任务门指向任务描述符
g_DemoTask: Gate g_DemoTssSelector, 0, 0, DA_TaskGate or DA_DPL2 ;386任务门指向任务描述符
GDTLen equ $ - GdtSeg ;GDT长度
;----------------------------------------------------------------------------
GDT_Ptr word GDTLen-1 ;VGDT
dword 0
_IDT_Ptr fword 0 ;VIDT
_RegSp word ? ;用于保存SS:SP
_RegSs word ?
;----------------------------------------------------------------------------
NormalSelector equ Normal - GdtSeg ;规范段选择子
g_DataSelector equ g_DataDesc - GdtSeg or SA_RPL3 ;全局数据段
g_CodeTempSelector equ g_CodeTempDesc - GdtSeg ;临时代码段选择子
g_DemoCodeSelector equ g_CodeSwitchDesc - GdtSeg ;任务切换代码段
g_VideoSelector equ g_VideoDesc - GdtSeg ;LDT视频段选择子
g_DemoTssSelector equ g_DemoTssDesc - GdtSeg ;TSS演示段描述符选择子
g_DemoLdtSelector equ g_DemoLdtDesc - GdtSeg ;演示代码段LDT描述符
g_TestTssSelector equ g_TestTssDesc - GdtSeg ;TSS测试段描述符选择子
g_TestLdtSelector equ g_TestLdtDesc - GdtSeg ;测试代码段的LDT
g_TestTaskSelector equ g_TestTask - GdtSeg ;测试代码任务门
g_DemoTaskSelector equ g_DemoTask - GdtSeg or SA_RPL2 ;演示任务任务门
g_IdtCodeSelector equ g_IdtCode32Desc - GdtSeg or SA_RPL1 ;中断处理代码
GdtSeg Ends
;============================================================================
LdtTestSeg Segment use32 ;测试任务段的LDT
; ;段基址 ;段界限 ;属性
L_TestStack1Desc: Descriptor 0, Stack_Len-1, DA_DRW or DA_DPL1 or DA_32 ;1环堆栈段
L_TestStack2Desc: Descriptor 0, Stack_Len-1, DA_DRW or DA_DPL2 or DA_32 ;1环堆栈段
L_TestStack3Desc: Descriptor 0, Stack_Len-1, DA_DRW or DA_DPL3 or DA_32 ;1环堆栈段
L_TestCode1Desc: Descriptor 0,TestCodeSegLen-1, DA_C or DA_32 or DA_DPL1 ;32位测试代码段
L_TestCode2Desc: Descriptor 0,TestCodeSegLen-1, DA_C or DA_32 or DA_DPL2 ;32位测试代码段
L_TestCode3Desc: Descriptor 0,TestCodeSegLen-1, DA_C or DA_32 or DA_DPL3 ;32位测试代码段
;----------------------------------------------------------------------------
L_TestCode1Selector equ L_TestCode1Desc - LdtTestSeg + SA_RPL1 + SA_TIL ;32位测试代码段选择子
L_TestCode2Selector equ L_TestCode2Desc - LdtTestSeg + SA_RPL2 + SA_TIL ;32位测试代码段选择子
L_TestCode3Selector equ L_TestCode3Desc - LdtTestSeg + SA_RPL3 + SA_TIL ;32位测试代码段选择子
L_TestStack1Selector equ L_TestStack1Desc - LdtTestSeg + SA_RPL1 + SA_TIL ;测试任务段的1环选择子
L_TestStack2Selector equ L_TestStack2Desc - LdtTestSeg + SA_RPL2 + SA_TIL ;测试任务段的1环选择子
L_TestStack3Selector equ L_TestStack3Desc - LdtTestSeg + SA_RPL3 + SA_TIL ;测试任务段的1环选择子
LdtTestSegLen equ $ - LdtTestSeg
LdtTestSeg Ends
;============================================================================
LdtDemoSeg Segment use32 ;演示代码段LDT
; ;段基址 ;段界限 ;属性
L_DemoCodeDesc: Descriptor 0,DemoCodeSegLen-1, DA_C or DA_32 ;32位代码段
L_DemoStackDesc: Descriptor 0, Stack_Len-1, DA_DRW or DA_32 ;演示代码段选择子
L_DemoStackSelector equ L_DemoStackDesc - LdtDemoSeg + SA_TIL ;演示代码堆栈选择子
L_DemoCodeSelector equ L_DemoCodeDesc - LdtDemoSeg + SA_TIL ;演示代码代码段选择子
LdtDemoSegLen equ $ - LdtDemoSeg
LdtDemoSeg Ends
;============================================================================
IdtSeg Segment use32 ;中断描述符表
repeat 13
Gate g_IdtCodeSelector, _IdtOther,0, DA_386TGate ;0-Ch陷阱门处理地址
endm
Gate g_IdtCodeSelector, _IdtGp, 0, DA_386TGate ;d通用故障处理
repeat 242
Gate g_IdtCodeSelector, _IdtOther,0, DA_386TGate ;e-256h陷阱门处理地址
endm
IdtSegLen equ $ - IdtSeg
IdtSeg Ends
;============================================================================
IdtCodeSeg Segment use32 ;中断处理代码
_IdtOther equ $ - IdtCodeSeg
IdtOther Proc ;其他类型的错误处理
;----------------------------------------------------------------------------
;edi, 已经被初始化了
lea esi, SzOther
mov ecx, sizeof SzOther ;显示其他错误字符串
cld
@@: lodsb
mov ah, 0ch
stosw
loop @b
iretd
IdtOther Endp
;----------------------------------------------------------------------------
_IdtGp equ $ - IdtCodeSeg ;通用故障处理
IdtGp Proc
;----------------------------------------------------------------------------
;显示错误字符串
mov esi, TestDataSeg
shl esi, 4
lea ecx, SzEroor
add esi, ecx ;esi-->字符串
mov ecx, sizeof SzEroor
cld
@@: lodsb
mov ah, 0ah
stosw
loop @b
;----------------------------------------------------------------------------
;将任务从忙置为闲
mov esi, GdtSeg
shl esi, 4
lea ecx, g_DemoTssDesc
add esi, ecx
mov al, byte ptr ds:[esi+5]
and al, 0f0h
or al, 9h ;将任务置为可用
mov byte ptr ds:[esi+5], al
;----------------------------------------------------------------------------
mov esp, Stack_Len ;跳过堆栈
;因为iretd中不能够作为任务返回, 所以这里使用JMP
Jmp32 g_DemoTaskSelector, 0
IdtGp Endp
IdtCodeSegLen equ $ - IdtCodeSeg
IdtCodeSeg Ends
;============================================================================
DemoTssSeg Segment use32 ;演示任务TSS段
DemoTss TSS <0>
byte 0ffh
DemoTssSegLen equ $ - DemoTssSeg
DemoTssSeg Ends
;============================================================================
DemoStackSeg Segment use32 ;演示代码段堆栈
byte Stack_Len dup (0)
DemoStackSeg Ends
;============================================================================
DemoCodeSeg Segment use32 ;演示代码段
_DemoBegin equ $ - DemoCodeSeg
DemoBegin Proc ;32位代码段入口
;----------------------------------------------------------------------------
;初始化自己的TSS, 用于在任务门中返回
mov ax, g_DataSelector ;全局数据段
mov ds, ax
mov ax, g_DemoLdtSelector
lldt ax ;装载LDTR
mov ax, L_DemoStackSelector
mov ss, ax
mov esp, Stack_Len ;置SS:ESP
xor edi, edi
mov edi, DemoTssSeg
shl edi, 4
lea ecx, DemoTss
add edi, ecx
mov word ptr ds:[edi+TSS.regLdtr], g_DemoLdtSelector;写入自己的LDTR
mov ax, g_DemoTssSelector
ltr ax ;装载演示段TR
;----------------------------------------------------------------------------
;初始化演示代码的TSS, 用于进行任务门转移
mov edi, TestTssSeg
shl edi, 4
lea ecx, StTestTss
add edi, ecx
;初始化TSS的SS:ESP
mov word ptr ds:[edi+TSS.regSs], L_TestStack1Selector
mov dword ptr ds:[edi+TSS.regEsp], Stack_Len
mov word ptr ds:[edi+TSS.regDs], g_DataSelector
;ds:esi-->>数据段--指向ds:SzCpl1, 5行5列
mov esi, TestDataSeg
shl esi, 4
lea eax, SzCpl1
add esi, eax
mov dword ptr ds:[edi+TSS.regEsi], esi
mov dword ptr ds:[edi+TSS.regEbx], 5 * 80 * 2 + 5 * 2
mov dword ptr ds:[edi+TSS.regEdi], 5 * 80 * 2 + (5 + sizeof SzCpl1 ) * 2
mov word ptr ds:[edi+TSS.regCs], L_TestCode1Selector
mov dword ptr ds:[edi+TSS.regEip], _TestCodeBegin
mov dword ptr ds:[edi+TSS.regEflags], IOPL1
mov word ptr ds:[edi+TSS.regLdtr], g_TestLdtSelector
;通过任务门转移到 测试任务TestCodeSeg-->_TestCodeBegin
CALL32 g_TestTaskSelector, 0
;----------------------------------------------------------------------------
;中断处理是1环的, 这里会异常, 所以填写1环的堆栈
mov word ptr ds:[edi+TSS.regSs], L_TestStack2Selector
mov dword ptr ds:[edi+TSS.regEsp], Stack_Len;初始化TSS的SS:ESP
mov word ptr ds:[edi+TSS.regSs1], L_TestStack1Selector
mov dword ptr ds:[edi+TSS.regEsp1], Stack_Len
;ds:esi-->>数据段--指向ds:SzCpl1, 5行5列
mov esi, TestDataSeg
shl esi, 4
lea eax, SzCpl2
add esi, eax
mov dword ptr ds:[edi+TSS.regEsi], esi
mov dword ptr ds:[edi+TSS.regEbx], 6 * 80 * 2 + 5 * 2
mov dword ptr ds:[edi+TSS.regEdi], 6 * 80 * 2 + ( 5 + sizeof SzCpl2 ) * 2
mov word ptr ds:[edi+TSS.regDs], g_DataSelector
mov word ptr ds:[edi+TSS.regCs], L_TestCode2Selector
mov dword ptr ds:[edi+TSS.regEip], _TestCodeBegin
mov dword ptr ds:[edi+TSS.regEflags], IOPL1 ;TSS的IOPL值
mov word ptr ds:[edi+TSS.regLdtr], g_TestLdtSelector
;通过任务门转移到 测试任务TestCodeSeg-->_TestCodeBegin
CALL32 g_TestTaskSelector, 0
;----------------------------------------------------------------------------
;这里再次测试敏感指令, 特权级位2 IOPL=1 会异常
mov word ptr ds:[edi+TSS.regSs], L_TestStack2Selector
mov dword ptr ds:[edi+TSS.regEsp], Stack_Len;初始化TSS的SS:ESP
mov word ptr ds:[edi+TSS.regSs1], L_TestStack1Selector
mov dword ptr ds:[edi+TSS.regEsp1], Stack_Len
;ds:esi-->>数据段--指向ds:SzCpl1, 5行5列
mov esi, TestDataSeg
shl esi, 4
lea eax, SzCpl3
add esi, eax
mov dword ptr ds:[edi+TSS.regEsi], esi
mov dword ptr ds:[edi+TSS.regEbx], 7 * 80 * 2 + 5 * 2
mov dword ptr ds:[edi+TSS.regEdi], 7 * 80 * 2 + ( 5 + sizeof SzCpl3 ) * 2
mov word ptr ds:[edi+TSS.regDs], g_DataSelector
mov word ptr ds:[edi+TSS.regCs], L_TestCode2Selector
mov dword ptr ds:[edi+TSS.regEip], _TestCode2Begin
mov dword ptr ds:[edi+TSS.regEflags], IOPL1 ;TSS的IOPL值
mov word ptr ds:[edi+TSS.regLdtr], g_TestLdtSelector
;通过任务门转移到 测试任务TestCodeSeg-->_TestCodeBegin
CALL32 g_TestTaskSelector, 0
;----------------------------------------------------------------------------
;这里再次测试敏感指令, 特权级位2 IOPL=2 但是执行了只有在0环才能够执行的特权指令
mov word ptr ds:[edi+TSS.regSs], L_TestStack2Selector
mov dword ptr ds:[edi+TSS.regEsp], Stack_Len;初始化TSS的SS:ESP
mov word ptr ds:[edi+TSS.regSs1], L_TestStack1Selector
mov dword ptr ds:[edi+TSS.regEsp1], Stack_Len
;ds:esi-->>数据段--指向ds:SzCpl1, 5行5列
mov esi, TestDataSeg
shl esi, 4
lea eax, SzCpl4
add esi, eax
mov dword ptr ds:[edi+TSS.regEsi], esi
mov dword ptr ds:[edi+TSS.regEbx], 8 * 80 * 2 + 5 * 2
mov dword ptr ds:[edi+TSS.regEdi], 8 * 80 * 2 + ( 5 + sizeof SzCpl4 ) * 2
mov word ptr ds:[edi+TSS.regDs], g_DataSelector
mov word ptr ds:[edi+TSS.regCs], L_TestCode2Selector
mov dword ptr ds:[edi+TSS.regEip], _TestCode2Begin
mov dword ptr ds:[edi+TSS.regEflags], IOPL2 ;TSS的IOPL值
mov word ptr ds:[edi+TSS.regLdtr], g_TestLdtSelector
;通过任务门转移到 测试任务TestCodeSeg-->_TestCodeBegin
CALL32 g_TestTaskSelector, 0
;----------------------------------------------------------------------------
;返回实模式
Jmp32 g_CodeTempSelector, _GoToProtect
DemoBegin Endp
;----------------------------------------------------------------------------
DemoCodeSegLen equ $ - DemoCodeSeg
DemoCodeSeg Ends
;============================================================================
TestStackSeg Segment use32
byte Stack_Len dup (0)
TestStackSeg Ends
;============================================================================
TestDataSeg Segment use32 ;测试代码段的数据段
SzCpl1 byte "Test Task1, CPL = 1; IOPL = 1!", 0
SzCpl2 byte "Test Task2, CPL = 2; IOPL = 1!", 0
SzCpl3 byte "Test Task3, CPL = 2; IOPL = 1!", 0
SzCpl4 byte "Test Task4, CPL = 2; IOPL = 2!", 0
SzEroor byte "#GP Error !", 0
SzOther byte "Other Error!", 0
TestDataSegLen equ $ - TestDataSeg
TestDataSeg Ends
;============================================================================
TestTssSeg Segment use32 ;测试任务TSS段
StTestTss TSS <0>
IoMap label byte ;IO许可位图
byte 8 dup ( 0ffh ) ;端口00h-3fh
byte 11111011b ;端口40h-47h
byte 3 dup ( 0ffh ) ;端口48h-5fh
byte 11111101b ;端口60h-67h
byte 0 ;端口68h-6fh
byte 0ffh ;端口结束标记
TestTssSegLen equ $ - TestTssSeg
TestTssSeg Ends
;============================================================================
TestCodeSeg Segment use32 ;测试代码段
;----------------------------------------------------------------------------
_MakeBeep Proc uses ebx esi edi ecx _dwPitch:dword;直接操作端口发出声音
;初始化定时器, 是向端口43H输出数据0B6H即可
mov al, 10110110y ;b6h
out 43h, al ; Timer 8253-5 (AT: 8254.2).
;向硬件定时器2(42h)端口写入1193167控制发声频率
mov eax, _dwPitch
out 42h, al
mov al, ah
out 42h, al
;打开扬声器
in al, 61h
or al, 11y
out 61h, al
DO_DELAY 20000h ;Bochs上面这个延时就可用了
;关闭扬声器
in al, 61h
and al, 11111100y
out 61h, al
ret
_MakeBeep Endp
;----------------------------------------------------------------------------
;显示一条信息_lpStr:字符串首地址
;_dwXY开始显示地址
_PrintMessage Proc uses esi edi _lpStr:dword, _dwXY:dword
mov esi, _lpStr
xor ecx, ecx
;----------------------------------------------------------------------------
@@: mov al, byte ptr ds:[esi]
inc esi
inc ecx
or al, al
jnz @b ;ecx == 字符串长度
dec ecx
;----------------------------------------------------------------------------
mov esi, _lpStr
mov edi, _dwXY
@@: lodsb
mov ah, 0ch ;属性红色字
stosw
loop @b
ret
_PrintMessage Endp
;----------------------------------------------------------------------------
;测试代码段入口, 测试一系列敏感指令
_TestCodeBegin equ $ - TestCodeSeg
TestCodeBegin Proc
mov ax, g_VideoSelector
mov es, ax
Invoke _PrintMessage, esi,ebx
Invoke _MakeBeep, TONE_1 ;发出个声音
;----------------------------------------------------------------------------
;此处证明了通过任务门, 可以用iretd返回, 或使用jmp32跳回去
iretd
;通过任务门切换回演示任务
;Jmp32 g_DemoTaskSelector, 0
;----------------------------------------------------------------------------
jmp TestCodeBegin
TestCodeBegin Endp
;----------------------------------------------------------------------------
;测试代码2入口, 测试一系列敏感指令
_TestCode2Begin equ $ - TestCodeSeg
TestCode2Begin Proc
mov ax, g_VideoSelector
mov es, ax
Invoke _PrintMessage, esi,ebx ;打印当前CPL和IOPL
cli
clts
iretd
jmp TestCode2Begin
TestCode2Begin Endp
TestCodeSegLen equ $ - TestCodeSeg
TestCodeSeg Ends
;============================================================================
;16位段, 由实模式跳入
;============================================================================
g_Code16Seg Segment use16
_GoToProtect Proc ;返回实模式
mov ax, NormalSelector
mov fs, ax ;规范选择子
mov es, ax
mov ds, ax
mov ss, ax
clts ;清除任务标记
mov eax, cr0 ;关PE位, 进入实模式
and al, 0feh
mov cr0, eax
;刷新段选择子缓冲区, 退回实模式
Jmp16 <seg StartCodeSeg >, < offset _RealProtect >
_GoToProtect Endp
;----------------------------------------------------------------------------
_ProtectEntry Proc ;实模式跳入入口
;16位转32位代码段
Jmp16 g_DemoCodeSelector, <_DemoBegin >
;----------------------------------------------------------------------------
_ProtectEntry Endp
g_Code16Seg Ends
;============================================================================
;起始代码段初始化保护模式的各个结构, 然后跳入保护模式
;============================================================================
StartCodeSeg Segment use16
_InitGdt Proc uses es ;初始化全局描述符表
xor eax, eax
mov ax, GdtSeg
mov es, ax ;es-->全局描述符表
;----------------------------------------------------------------------------
shl eax, 4
mov dword ptr es:[GDT_Ptr+2], eax ;初始化VGDT描述符
;----------------------------------------------------------------------------
xor eax, eax
mov ax, g_Code16Seg ;初始化十六位的代码段
shl eax, 4
mov word ptr es:[g_CodeTempDesc+2], ax ;段基址低位
shr eax, 16
mov byte ptr es:[g_CodeTempDesc+4], al ;段基址高地址低位
mov byte ptr es:[g_CodeTempDesc+7], ah ;段基址高地址高位
;----------------------------------------------------------------------------
xor eax, eax
mov ax, DemoTssSeg ;初始化演示TSS段描述符
shl eax, 4
mov word ptr es:[g_DemoTssDesc+2], ax
shr eax, 16
mov byte ptr es:[g_DemoTssDesc+4], al
mov byte ptr es:[g_DemoTssDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, TestTssSeg ;初始化测试TSS段描述符
shl eax, 4
mov word ptr es:[g_TestTssDesc+2], ax
shr eax, 16
mov byte ptr es:[g_TestTssDesc+4], al
mov byte ptr es:[g_TestTssDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, DemoCodeSeg ;初始化任务切换段
shl eax, 4
mov word ptr es:[g_CodeSwitchDesc+2], ax
shr eax, 16
mov byte ptr es:[g_CodeSwitchDesc+4], al
mov byte ptr es:[g_CodeSwitchDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, LdtTestSeg ;初始化测试代码段的LDT
shl eax, 4
mov word ptr es:[g_TestLdtDesc+2], ax
shr eax, 16
mov byte ptr es:[g_TestLdtDesc+4], al
mov byte ptr es:[g_TestLdtDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, LdtDemoSeg ;初始化测试代码段的LDT
shl eax, 4
mov word ptr es:[g_DemoLdtDesc+2], ax
shr eax, 16
mov byte ptr es:[g_DemoLdtDesc+4], al
mov byte ptr es:[g_DemoLdtDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, IdtCodeSeg ;初始化测试代码段的LDT
shl eax, 4
mov word ptr es:[g_IdtCode32Desc+2], ax
shr eax, 16
mov byte ptr es:[g_IdtCode32Desc+4], al
mov byte ptr es:[g_IdtCode32Desc+7], ah
;----------------------------------------------------------------------------
lgdt fword ptr es:[GDT_Ptr] ;装载GDT
;----------------------------------------------------------------------------
ret
_InitGdt Endp
;----------------------------------------------------------------------------
_InitDemoLdt Proc uses es ;初始化演示代码段LDT
mov ax, LdtDemoSeg
mov es, ax
;----------------------------------------------------------------------------
xor eax, eax
mov ax, DemoStackSeg ;初始化演示代码段堆栈
shl eax, 4
mov word ptr es:[L_DemoStackDesc+2], ax
shr eax, 16
mov byte ptr es:[L_DemoStackDesc+4], al
mov byte ptr es:[L_DemoStackDesc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, DemoCodeSeg ;初始化32位代码段
shl eax, 4
mov word ptr es:[L_DemoCodeDesc+2], ax
shr eax, 16
mov byte ptr es:[L_DemoCodeDesc+4], al
mov byte ptr es:[L_DemoCodeDesc+7], ah
;----------------------------------------------------------------------------
ret
_InitDemoLdt Endp
;----------------------------------------------------------------------------
_InitTestLdt Proc uses es ;初始化测试代码段LDT
mov ax, LdtTestSeg
mov es, ax
;----------------------------------------------------------------------------
xor eax, eax
mov ax, TestStackSeg ;初始化1环堆栈段
shl eax, 4
mov word ptr es:[L_TestStack1Desc+2], ax
mov word ptr es:[L_TestStack2Desc+2], ax
mov word ptr es:[L_TestStack3Desc+2], ax
shr eax, 16
mov byte ptr es:[L_TestStack1Desc+4], al
mov byte ptr es:[L_TestStack2Desc+4], al
mov byte ptr es:[L_TestStack3Desc+4], al
mov byte ptr es:[L_TestStack1Desc+7], ah
mov byte ptr es:[L_TestStack2Desc+7], ah
mov byte ptr es:[L_TestStack3Desc+7], ah
;----------------------------------------------------------------------------
xor eax, eax
mov ax, TestCodeSeg ;初始化测试代码段
shl eax, 4
mov word ptr es:[L_TestCode1Desc+2], ax
mov word ptr es:[L_TestCode2Desc+2], ax
mov word ptr es:[L_TestCode3Desc+2], ax
shr eax, 16
mov byte ptr es:[L_TestCode1Desc+4], al
mov byte ptr es:[L_TestCode2Desc+4], al
mov byte ptr es:[L_TestCode3Desc+4], al
mov byte ptr es:[L_TestCode1Desc+7], ah
mov byte ptr es:[L_TestCode2Desc+7], ah
mov byte ptr es:[L_TestCode3Desc+7], ah
;----------------------------------------------------------------------------
ret
_InitTestLdt Endp
;----------------------------------------------------------------------------
_InitIdt Proc uses ds ;初始化中断描述符表
local _Vidt:fword
xor eax,eax
mov ax, GdtSeg
mov ds, ax
;----------------------------------------------------------------------------
sidt fword ptr ds:[_IDT_Ptr] ;保存IDT
mov word ptr ss:[_Vidt], IdtSegLen ;IDT长度
mov eax, IdtSeg
shl eax, 4
mov dword ptr ss:[_Vidt+2], eax
cli
lidt fword ptr ss:[_Vidt] ;装载IDT
;----------------------------------------------------------------------------
ret
_InitIdt Endp
;----------------------------------------------------------------------------
Jmain Proc
call _InitGdt ;初始化GDT全局描述符
call _InitDemoLdt ;初始化演示代码段LDT
call _InitTestLdt ;初始化测试代码段LDT
call _InitIdt ;初始化IDT
;----------------------------------------------------------------------------
mov ax, GdtSeg
mov ds, ax
mov ds:[_RegSs], ss
mov ds:[_RegSp], sp ;保存SS:SP
_EnableA20 ;开A20地址线
mov eax, cr0
or eax, 1
mov cr0, eax ;开启分段, 进入保护模式
xor ax, ax
mov es, ax
;----------------------------------------------------------------------------
Jmp16 g_CodeTempSelector, <offset _ProtectEntry>;跳入保护模式
Jmain Endp
;----------------------------------------------------------------------------
_RealProtect Proc ;返回保护模式
mov ax, GdtSeg
mov ds, ax
lss sp, dword ptr ds:[_RegSp] ;恢复SS:SP
lidt fword ptr ds:[_IDT_Ptr] ;恢复IDT
_DisableA20 ;关A20地址线, 开中断
sti
mov ax, 4c00h
int 21h
_RealProtect Endp
StartCodeSeg Ends
End Jmain
|