‘===============
页目录表或页 表的表项格式 |
BIT31—BIT12 | BIT11—BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
物理页码 | AVL | 0 | 0 | D | A | 0 | 0 | U/S | R/W | P |
mov eax,cr3 mov cr3,eax
页级 保护 属性 |
U/S | R/W | 用户级访问权限 | 系统级访问权限 |
0 | 0 | 无 | 读/写/执行 | |
0 | 1 | 无 | 读/写/执行 | |
1 | 0 | 读/执行 | 读/写/执行 | |
1 | 1 | 读/写/执行 | 读/写/执行 |
组合页的 保护>属性 |
目录表项U/S | 页表项U/S | 组合U/S | 目录表项R/W | 页表项R/W | 组合R/W |
0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 0 | 0 | 1 | 0 | |
1 | 0 | 0 | 1 | 0 | 0 | |
1 | 1 | 1 | 1 | 1 | 1 |
出错码 的格式 |
BIT15—BIT3 | BIT2 | BIT1 | BIT0 |
未使用 | U | W | P |
;名称:ASM10.ASM ;功能:演示使用分页管理机制 ;编译:TASM ASM10.ASM ;连接:TLINK ASM10.OBJ ;============================================================================ INCLUDE 386SCD.INC ;============================================================================ PDT_AD = 200000h ;页目录表所在物理页的地址 PT0_AD = 202000h ;页表0所在物理页的地址 PT1_AD = 201000h ;页表1所在物理页的地址 PhVB_AD = 0b8000h ;物理视频缓冲区地址 LoVB_AD = 0f0000h ;程序使用的逻辑视频缓冲区地址 MPVB_AD = 301000h ;线性地址0B8000H所映射的物理地址 PhSC_AD = 303000h ;部分演示代码所在内存的物理地址 LoSC_AD = 402000h ;部分演示代码的逻辑地址 ;============================================================================ GDTSeg SEGMENT PARA USE16 ;全局描述符表数据段(16位) ;---------------------------------------------------------------------------- ;全局描述符表GDT GDT LABEL BYTE ;空描述符 DUMMY Desc <> ;规范段描述符及选择子 Normal Desc <0ffffh,,,ATDW,,> Normal_Sel = Normal-GDT ;页目录表所在段描述符(在保护方式下初始化时用)及选择子 PDT Desc <0fffh,PDT_AD AND 0ffffh,PDT_AD SHR 16,ATDW,,> PDT_Sel = PDT-GDT ;页表0所在段描述符(在保护方式下初始化时用)及选择子 PT0 Desc <0fffh,PT0_AD AND 0ffffh,PT0_AD SHR 16,ATDW,,> PT0_Sel = PT0-GDT ;页表1所在段描述符(在保护方式下初始化时用)及选择子 PT1 Desc <0fffh,PT1_AD AND 0ffffh,PT1_AD SHR 16,ATDW,,> PT1_Sel = PT1-GDT ;逻辑视频缓冲区段描述符及选择子 LoVideo Desc <3999,LoVB_AD AND 0ffffh,LoVB_AD SHR 16,ATDW,,> LoVideo_Sel = LoVideo-GDT ;逻辑上的部分演示代码段的描述符及选择子 LoCode Desc <SCodeLen-1,LoSC_AD AND 0ffffh,LoSC_AD SHR 16,ATCE,,> LoCode_Sel = LoCode-GDT ;预定内存区域(用于部分演示代码)的段描述符及选择子 TPSCode Desc <SCodeLen-1,PhSC_AD AND 0ffffh,PhSC_AD SHR 16,ATDW,,> TPSCode_Sel = TPSCode-GDT ;---------------------------------------------------------------------------- ;以下是需额外初始化的描述符 EFFGDT LABEL BYTE ;临时代码段描述符及选择子 TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,> TempCode_Sel = TempCode-GDT ;演示代码段描述符及选择子 DemoCode Desc <DemoCodeLen-1,DemoCodeSeg,,ATCE,,> DemoCode_Sel = DemoCode-GDT ;演示任务数据段描述符及选择子 DemoData Desc <DemoDataLen-1,DemoDataSeg,,ATDW,,> DemoData_Sel = DemoData-GDT ;初始化时要移动的代码段描述符及选择子(移动时作为数据对待) SCode Desc <SCodeLen-1,SCodeSeg,,ATDR,,> SCode_Sel = SCode-GDT ;---------------------------------------------------------------------------- GDTLen = $-GDT ;全局描述符表长度 GDNum = ($-EFFGDT)/(SIZE Desc) ;需特殊处理的描述符数 ;---------------------------------------------------------------------------- GDTSeg ENDS ;全局描述符表段定义结束 ;============================================================================ ;这部分代码在初始化时被复制到预定的内存区域,其功能是在屏幕上显示提示信息 ;---------------------------------------------------------------------------- SCodeSeg SEGMENT PARA USE16 ASSUME CS:SCodeSeg,DS:DemoDataSeg ;---------------------------------------------------------------------------- SBegin PROC FAR mov ax,LoVideo_Sel mov es,ax mov di,0 mov ah,17h mov cx,MessLen S1: lodsb stosw loop S1 JUMP16 DemoCode_Sel,Demo3 SBegin ENDP ;---------------------------------------------------------------------------- MLen = $-SBegin SCodeLen = $ SCodeSeg ENDS ;============================================================================ DemoDataSeg SEGMENT PARA USE16 ;演示任务数据段 Mess DB 'Page is OK!' MessLen = $-Mess DemoDataLen = $ DemoDataSeg ENDS ;============================================================================ DemoCodeSeg SEGMENT PARA USE16 ;演示任务代码段 ASSUME CS:DemoCodeSeg ;---------------------------------------------------------------------------- DemoBegin PROC FAR mov ax,PDT_Sel mov es,ax xor di,di mov cx,1024 xor eax,eax ;先把全部表项置成无效 rep stosd ;再置表项0和表项1 mov DWORD PTR es:[0],PT0_AD OR (USU+RWW+PL) mov DWORD PTR es:[4],PT1_AD OR (USU+RWW+PL) mov ax,PT0_Sel ;初始化页表0 mov es,ax xor di,di mov cx,1024 xor eax,eax or eax,USU+RWW+PL Demo1: stosd add eax,1000h ;先全部置成对应等地址的 loop Demo1 ;物理页,再特别设置两广表项 mov di,(PhVB_AD SHR 12)*4 mov DWORD PTR es:[di],MPVB_AD+USS+RWW+PL mov di,(LoVB_AD SHR 12)*4 mov DWORD PTR es:[di],PhVB_AD+USU+RWR+PL mov ax,PT1_Sel ;初始化页表1 mov es,ax xor di,di mov cx,1024 mov eax,400000h Demo2: stosd ;先把全部表项设置为无效 add eax,1000h loop Demo2 ;再特别设置1项 mov di,((LoSC_AD SHR 12)AND 3ffh)*4 mov DWORD PTR es:[di],PhSC_AD+USU+RWR+PL mov eax,PDT_AD mov cr3,eax mov eax,cr0 or eax,80000000h mov cr0,eax jmp SHORT PageE PageE: mov ax,DemoData_Sel mov ds,ax mov si,OFFSET Mess JUMP16 LoCode_Sel,SBegin Demo3: mov eax,cr0 and eax,7fffffffh ;关闭分页机制 mov cr0,eax jmp SHORT PageD PageD: mov ax,Normal_Sel JUMP16 TempCode_Sel,ToDOS DemoBegin ENDP ;---------------------------------------------------------------------------- DemoCodeLen = $ DemoCodeSeg ENDS ;============================================================================ TempCodeSeg SEGMENT PARA USE16 ;临时任务的代码段 ASSUME CS:TempCodeSeg ;---------------------------------------------------------------------------- Virtual PROC FAR cld ;为演示在启用分页机制后执 mov ax,SCode_Sel ;行位于较高线性地址空间中 mov ds,ax ;的代码作准备 mov ax,TPSCode_Sel mov es,ax mov si,OFFSET SBegin mov di,si mov cx,MLen ;把分页演示代码复制到预定 rep movsb ;内存 JUMP16 DemoCode_Sel,DemoBegin ToDOS: mov ds,ax mov es,ax mov eax,cr0 ;准备返回实模式 and al,11111110b mov cr0,eax JUMP16 <SEG Real>,<OFFSET Real> Virtual ENDP ;---------------------------------------------------------------------------- TempCodeSeg ENDS ;============================================================================ RCodeSeg SEGMENT PARA USE16 ;实方式的初始化代码和数据 ASSUME CS:RCodeSeg,DS:RCodeSeg ;---------------------------------------------------------------------------- VGDTR PDesc <GDTLen-1,> ;---------------------------------------------------------------------------- Start PROC push cs pop ds cld call InitGDT ;初始化全局描述符表GDT EnableA20 lgdt QWORD PTR VGDTR ;装载GDTR cli ;关中断 mov eax,cr0 or al,1 mov cr0,eax JUMP16 <TempCode_Sel>,<OFFSET Virtual> Real: DisableA20 sti mov ax,4c00h int 21h Start ENDP ;---------------------------------------------------------------------------- InitGDT PROC push ds mov ax,GDTSeg mov ds,ax mov cx,GDNum mov si,OFFSET EFFGDT InitG: mov ax,[si].BaseL movzx eax,ax shl eax,4 shld edx,eax,16 mov WORD PTR [si].BaseL,ax mov BYTE PTR [si].BaseM,dl mov BYTE PTR [si].BaseH,dh add si,SIZE Desc loop InitG pop ds mov bx,16 mov ax,GDTSeg mul bx mov WORD PTR VGDTR.Base,ax mov WORD PTR VGDTR.Base+2,dx ret InitGDT ENDP ;---------------------------------------------------------------------------- RCodeSeg ENDS END Start
mov eax,cr0 or eax,80000000h mov cr0,eax jmp SHORT PageE PageE: ...