发信人: Reinhard.bbs@bbs.sjtu.edu.cn (摘星), 信区: cnhacker
标 题: 80386 保护模式简介 -1 by 软蛀 -- Alex 整理(转寄)
发信站: 饮水思源站 (Fri Apr 25 20:35:51 1997)
转信站: Lilac!ustcnews!ustcnews!sjtunews!sjtubbs
出 处: bbs.sjtu.edu.cn
section 1 of 1 of file protect.zip
┌┐┌┐∞
【 80386保护模式简介 】 ┘└┘└┘
--------------------------------------------------------------------------
在保护模式下有很多新的名词 ,包含 GDT.LDT.IDT 以及 CR0-CR3 ,笔者对保护
模式并不清楚 ,所以底下资料可能有错误。这里使用大量的线性记忆体观念 ,请您
一定要从头往後看 ,否则很可能会看不懂 ,且必须懂线性记忆体计算方式。
--------------------------------------------------------------------------
【 GDT 介绍 】
在真实模式下每个区段都等於64K ,可是保护模式下每个区段的大小却是可变动
的 ,每个区段有多大呢 ,就是由 GDT 来决定。
您可以用 SGDT CS:[BX] 的方式将 GDT 的值读出 ,它的长度为 6 BYTE ,底下
是笔者写的小程式读出。
XXXX:0000 FF 0F 00 20 C0 00
^^^^^^^^^^^GDT表所在的线性记忆体位址
^^^^^GDT表长度+1
将此表资料读出来.
X:00C02000 00 00 00 00 00 00 00 00-FF FF 00 A0 C2 9B 40 00 ........... B.@.
X:00C02010 FF FF B0 DD 01 93 40 00-FF FF E0 B3 00 9A 00 00 ..0]..@...`3....
X:00C02020 FF FF E0 B3 00 93 00 00-00 00 00 20 C1 82 80 00 ..`3....... A...
X:00C02030 00 00 00 20 C1 93 C0 00-00 00 00 20 C0 93 C0 00 ... A.@.... @.@.
X:00C02040 00 00 00 00 00 92 40 00-FF FF 00 80 0B 92 40 00 ......@.......@.
.
.
.
.
它所代表的意思是如下图所示:(每组 8 byte)
┌——————————————————————┐
1│ Limit bit 0-15 │ 0 byte
├——————————————————————┤
3│ Base bit 0-15 │ 2
├——————————┬———————————┤
5│ 存取权 │ Base bit 16-23 │ 4
├——————————┼———————————┤
7│ Base bit 24-31 │G│..│limit bit 16-19│ 6
└——————————┴———————————┘
"G"代表 Limit 的单位是 Byte 或 PAGE(4K)
所以....
#0000 Segment not present.
#0008 Base=00C2A000 Limit=0000FFFF Flags=9B USE32 Byte granularity
#0010 Base=0001DDB0 Limit=0000FFFF Flags=93 USE32 Byte granularity
#0018 Base=0000B3E0 Limit=0000FFFF Flags=9A USE16 Byte granularity
#0020 Base=0000B3E0 Limit=0000FFFF Flags=93 USE16 Byte granularity
#0028 Base=00C12000 Limit=00000000 Flags=82 Page granularity
#0030 Base=00C12000 Limit=00000000 Flags=93 USE32 Page granularity
#0038 Base=00C02000 Limit=00000000 Flags=93 USE32 Page granularity
#0040 Base=00000000 Limit=00000000 Flags=92 USE32 Byte granularity
#0048 Base=000B8000 Limit=0000FFFF Flags=92 USE32 Byte granularity
#0050 Base=0001F56C Limit=000007FF Flags=92 USE32 Byte granularity
#0058 Base=00000000 Limit=00000144 Flags=92 USE32 Page granularity
#0060 Base=00000000 Limit=00000144 Flags=93 USE32 Page granularity
#0068 Base=00127F48 Limit=0000C32F Flags=9B USE16 Byte granularity
#0070 Base=00134278 Limit=000028F7 Flags=93 USE16 Byte granularity
#0078 Base=00000000 Limit=00000000 Flags=92 USE16 Byte granularity
^^^^^Selector ^^存取权
Base 就是指这个Secector:00000000对应到线性记忆体的何处 ,也就是说将线性记
忆体从 Base 所指的地方开始长度为 Limit ,剪下来变成一个独立的区段 ,如果您
在该区段想看超过 LIMIT 长度的记忆体 ,则会发生保护模式错误...应用程式可拦
截所发生的中断适当的加以处理。
注意 ,Limit的单位可以是 byte ,也可以是page(4k) ,由 "G" 是否为 1 来决定
至於 Selector 的数值我猜想应该是被标上 8 的倍数吧 ,因为很多书都是如此介
绍它。
--------------------------------------------------------------------------
【 LDT 介绍 】
上面介绍了 GDT 可以设定很多个Secector ,而 LDT 则是在这些被定义出来
的Selector中再切割出更小的单元。也就是说 LDT 的资料长度只有 2 BYTE ,这
个值直接就是指 Selector。
※这个命令必需在最高权力下才能执行 ,所以笔者使用 386DEBUG 来执行 ,在传
统 Real Mode/V86 都不能执行。
C:\>386debug 386debug.exp (改过的.exp档)
000C:0002743C 660F0007 SLDT [EDI]
-T
-D EDI
0014:00000000 28 00 <-- LDT 所指的Selector为0028
根据 GDT 的资料查表得到下表 ,但是由於 0028 这段落禁止观看 ,所以我改看0030
的段落 ,因为它的 Base 是一样的。
#0028 Base=00C12000 Limit=00000000 Flags=82 Page granularity
#0030 Base=00C12000 Limit=00000000 Flags=93 USE32 Page granularity
-D 30:0
0030:00000000 FF 00 F0 CE 09 92 40 00-31 00 00 00 CA 9B C0 00 ..pN..@.1...J.@.
0030:00000010 31 00 00 00 CA 93 C0 00-FF FF 00 80 0B 92 40 00 1...J.@.......@.
0030:00000020 FF 00 F0 CE 09 92 40 00-4D 00 90 CE 09 92 40 00 ..pN..@.M..N..@.
0030:00000030 44 01 00 00 00 93 C0 00-00 00 00 00 00 92 40 00 D.....@.......@.
0030:00000040 FF FF 00 80 0B 92 40 00-00 00 00 00 00 92 40 00 ......@.......@.
0030:00000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0030:00000060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0030:00000070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-DL 0
#0004 Base=0009CEF0 Limit=000000FF Flags=92 USE32 Byte granularity
#000C Base=00CA0000 Limit=00000031 Flags=9B USE32 Page granularity
#0014 Base=00CA0000 Limit=00000031 Flags=93 USE32 Page granularity
#001C Base=000B8000 Limit=0000FFFF Flags=92 USE32 Byte granularity
#0024 Base=0009CEF0 Limit=000000FF Flags=92 USE32 Byte granularity
#002C Base=0009CE90 Limit=0000004D Flags=92 USE32 Byte granularity
#0034 Base=00000000 Limit=00000144 Flags=93 USE32 Page granularity
#003C Base=00000000 Limit=00000000 Flags=92 USE32 Byte granularity
#0044 Base=000B8000 Limit=0000FFFF Flags=92 USE32 Byte granularity
#004C Base=00000000 Limit=00000000 Flags=92 USE32 Byte granularity
#0054 Segment not present.
#005C Segment not present.
#0064 Segment not present.
#006C Segment not present.
#0074 Segment not present.
#007C Segment not present.
--------------------------------------------------------------------------
【 IDT 介绍 】
在以往中断向量表都是用 4 byte 来表示 ,但是在保护模式下则由 8 byte 表
示 ,至於那几个 byte 表示什麽 ,笔者还未搞懂 ,底下只弄懂几个。
C:\>386debug 386debug.exp (改过的.exp档)
000C:00027434 660F010F SIDT [EDI]
-D EDI
0014:00000000 FF 07 6C F5 01 00 .. ..-.. .. .. .. .. .. .. ..
^^^^^^^^^^^线性记忆体位址
^^^^^长+1
因为该线性记忆体已对映到 50:0
#0050 Base=0001F56C Limit=000007FF Flags=92 USE32 Byte granularity
所以:
0050:00000000 00 34 08 00 00 EE 00 00-0A 34 08 00 00 EE 00 00 .4...n...4...n..
0050:00000010 14 34 08 00 00 EE 00 00-1E 34 08 00 00 EE 00 00 .4...n...4...n..
0050:00000020 28 34 08 00 00 EE 00 00-32 34 08 00 00 EE 00 00 (4...n..24...n..
0050:00000030 3C 34 08 00 00 EE 00 00-6C 16 C8 0F 00 8E 00 00 <4...n..F4...n..
0050:00000040 50 34 08 00 00 EE 00 00-5A 34 08 00 00 EE 00 00 P4...n..Z4...n..
0050:00000050 64 34 08 00 00 EE 00 00-6E 34 08 00 00 EE 00 00 d4...n..n4...n..
0050:00000060 78 34 08 00 00 EE 00 00-82 34 08 00 00 EE 00 00 x4...n...4...n..
0050:00000070 8C 34 08 00 00 EE 00 00-96 34 08 00 00 EE 00 00 .4...n...4...n..
-DI 0
#0000 Selector=0008 Offset=00003400 Flags=EE ;int_0
#0001 Selector=0008 Offset=0000340A Flags=EE ;int_1
#0002 Selector=0008 Offset=00003414 Flags=EE ;int_2
#0003 Selector=0008 Offset=0000341E Flags=EE ;int_3
#0004 Selector=0008 Offset=00003428 Flags=EE
#0005 Selector=0008 Offset=00003432 Flags=EE
#0006 Selector=0008 Offset=0000343C Flags=EE
#0007 Selector=0FC8 Offset=0000166C Flags=8E ;此处为Q387使用
#0008 Selector=0008 Offset=00003450 Flags=EE
#0009 Selector=0008 Offset=0000345A Flags=EE
#000A Selector=0008 Offset=00003464 Flags=EE
#000B Selector=0008 Offset=0000346E Flags=EE
#000C Selector=0008 Offset=00003478 Flags=EE
#000D Selector=0008 Offset=00003482 Flags=EE
#000E Selector=0008 Offset=0000348C Flags=EE
#000F Selector=0008 Offset=00003496 Flags=EE
请仔细看一看这个表的对应情形 ,笔者故意载入Q387 以便让 INT_7 的 Selector 与
众不同 ,让您更易判断中断表对应关系。
--------------------------------------------------------------------------
实例解说:
底下是读取 SoftICE INT_0 的程式码□例:
Load IDT
LDT = FF 07 12 C0 80 00 所以观看 0080C012 的记忆体
0080C012 47 2C 18 00 00 EE 00 00-4C 2C 18 00 00 EE 00 00 G,...□.L,...□.
0080C022 51 2C 18 00 00 EE 00 00-56 2C 18 00 00 EE 00 00 Q,...□.V,...□.
0080C032 5B 2C 18 00 00 EE 00 00-60 2C 18 00 00 EE 00 00 [,...□.`,...□.
0080C042 65 2C 18 00 00 EE 00 00-6A 2C 18 00 00 EE 00 00 e,...□.j,...□.
0080C052 6F 2C 18 00 00 EE 00 00-74 2C 18 00 00 EE 00 00 o,...□.t,...□.
0080C062 79 2C 18 00 00 EE 00 00-7E 2C 18 00 00 EE 00 00 y,...□.~,...□.
由此得知 INT_0 是放在 0018:00002C47 的位址 ,於是查GDT表..
Load GDT
GDT = C8 00 18 C8 80 00 所以观看 0080C818 的记忆体
0080C818 00 00 00 00 00 00 00 00-FF FF 10 11 83 93 00 00 ............儞..
0080C828 FF FF 00 6E 81 93 00 00-FF FF 00 6E 81 9B 00 00 ...n亾.....n仜..
0080C838 FF FF 00 00 00 93 CF 00-FF 7F 00 00 0B 92 00 00 .....摗.....
0080C848 FF 7F 00 80 0B 92 00 00-FF FF 00 00 0C 92 00 00 ...........
0080C858 FF FF F0 32 82 9A 00 00-FF FF 00 C0 80 93 C0 00 ..□倸.....□摗
0080C868 0F 00 00 C0 7F 92 C0 00-68 20 00 00 81 8B 00 00 ...□挕鮤 ..亱..
得到 Selector=0018=线性记忆体位址 816E00 处
於是我们就可以得知该中断程式放在 816E00:2C47 了 ,於是笔者把 816E00 的记忆体
搬到 8000:0000 ,然後用 DEBUG 来查看。
-u 8000:2c47
8000:2C47 6A00 PUSH 00
8000:2C49 E9F4D6 JMP 0340
8000:2C4C 6A01 PUSH 01
8000:2C4E E9C7D8 JMP 0518
8000:2C51 6A02 PUSH 02
8000:2C53 E98ADC JMP 08E0
8000:2C56 6A03 PUSH 03
8000:2C58 E9D6DC JMP 0931
8000:2C5B 6A04 PUSH 04
8000:2C5D E9E0D6 JMP 0340
8000:2C60 6A05 PUSH 05
8000:2C62 E9DBD6 JMP 0340
8000:2C65 6A06 PUSH 06
8000:2C67 E943DF JMP 0BAD
8000:2C6A 6A07 PUSH 07
8000:2C6C E975E0 JMP 0CE4
8000:2C6F 6A08 PUSH 08
8000:2C71 E97BE1 JMP 0DEF
8000:2C74 6A09 PUSH 09
8000:2C76 E91605 JMP 318F
8000:2C79 6A0A PUSH 0A
8000:2C7B E9C4D5 JMP 0242
8000:2C7E 6A0B PUSH 0B
8000:2C80 E9BFD5 JMP 0242
--------------------------------------------------------------------------
看了上面几个例子後 ,再来就是练习进入保护模式 ,底下的例子请勿载入 EMM 系
列的保护模式软体 ,以免等级权限相冲当机。
code segment
assume cs:code,ds:code
start proc near
jmp next
buffer1 db 18h,00h,00h,00h,00h,00h
; ---+--- ------+--------
; | |
; | |
; | GDT 表的记忆体位址
; |
; +----------GDT 表的长度
;
;
buffer2 db 000h,000h,000h,000h,000h,000h,000h,000h ;保留段
db 0ffh,0ffh,000h,000h,000h,09bh,000h,000h ;程式段code:0
db 0ffh,0ffh,000h,080h,00bh,093h,000h,000h ;萤幕段B800:0
db 0100h dup (0)
; ------+-------
; |
; |
; 线性记忆体位址
;
msg_1 db 'Enter Protect Mode !'
msg_2 db 0dh,0ah,'Return Real Mode !',0dh,0ah,'$'
386p
next :
mov ax,0600h ;
mov bx,0700h ;
mov cx,0000h ;
mov dx,184fh ;
int 10h ; CLS
mov ah,02h ;
mov bh,00h ;
mov dx,0100h ;
int 10h ;
mov ax,cs
mov ds,ax
mov es,ax
xor eax,eax
xor ebx,ebx
mov ax,cs
mov cl,04h
shl eax,cl
mov bx,offset buffer2
add eax,ebx
mov bx,offset buffer1+2
mov cs:[bx],eax ;GDT 位址设定
NOP
xor eax,eax
xor ebx,ebx
mov ax,cs
mov cl,04h
shl eax,cl
add eax,ebx
mov bx,offset buffer2
mov cs:[bx+0ah],eax ;GDT Table 设定
mov byte ptr cs:[bx+0dh],9bh ;存取权
mov ax,cs
mov ds,ax
mov es,ax
mov bx,offset buffer1
xor ecx,ecx
cli
cli
lgdt cs:[bx] ;载入GDT
mov eax,cr0
or eax,01h
mov cr0,eax
jmp protection ;进入保护模式
protection :
db 66h
mov ax,code
mov ds,ax
mov si,offset msg_1
mov bx,0010h
mov es,bx
mov di,0000h
mov cx,0014h
mov ah,70h
show :
cld ;将CS:MSG_1搬到 0010:00000000
lodsb ;(0010的区段=B8000 请参考GDT
stosw ; 表)
loop show ;
mov eax,cr0
and al,not 1
mov cr0,eax
db 0eah
dw real_mode,code ;返回真实模式
real_mode :
sti
mov ax,cs
mov ds,ax
mov ah,09h
mov dx,offset msg_2
int 21h
mov ax,4cffh
int 21h
start endp
code ends
end start
--------------------------------------------------------------------------
上面这个例子并没有设定 IDT (中断表) ,如果您要设定中断表的话 ,记得返回
真实模式时要还原 IDT 表.
--------------------------------------------------------------------------
如果您希望在载入 QEMM386 後还能正常进入保护模式的话 ,则必需透过 VCPI
的命令来切入保护模式 ,详情可翻阅 VCPI 的书籍。
-- 软蛀 --
--
沉默的人
Reinhard Young
※ 来源:·饮水思源站 bbs.sjtu.edu.cn·[FROM: 202.96.212.29]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:215.240毫秒