3.3.7进一步体会分页机制
来源:互联网 发布:java成神之路 编辑:程序博客网 时间:2024/06/04 19:46
DA_C EQU 98h ; 存在的只执行代码段属性值
DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
LABEL_DESC_CODE32:Descriptor 0, SegCode32Len - 1, DA_CR +DA_32;把DA_C 改成DA_CR
在定义LABEL_DESC_CODE32里面把属性没有改好,结果这个错误导致DOS系统崩溃,但现在还不能理解DA_C与DA_CR的用法区别。
PS:EditPlus字体设置成Fixedys,比较符合我个人的习惯。还有要把它装在MSMA32下面才会有语法高亮
惯例附加代码:
;有三个问题,第一个是TestRead和TestWrite ,DispAL,DispReturn要放在段[SECTION .s32]里面
; 第二个问题是:显示还不能正确显示转换后的字符,为什么?
;对于NORMAL的真正作用暂时还没弄明白;
%include "pm.inc"
;%include "lib.inc" ; 库函数 当把lib.inc的库函数放在这里是不行的,要放在SegCode32Len 的前面才可以正确显示,为什么呢?
PageDirBase0 equ 200000h ; 页目录开始地址: 2M
PageTblBase0 equ 201000h ; 页表开始地址: 2M + 4K
PageDirBase1 equ 210000h ; 页目录开始地址: 2M + 64K
PageTblBase1 equ 211000h ; 页表开始地址: 2M + 64K + 4K
LinearAddrDemo equ 00401000h
ProcFoo equ 00401000h
ProcBar equ 00501000h
ProcPagingDemo equ 00301000h
org 0100h
jmp LABEL_BEGIN
[SECTION .gdt]
;GDT
LABEL_GDT: Descriptor 0, 0, 0
LABEL_DESC_CODE32:Descriptor 0, SegCode32Len - 1, DA_CR +DA_32;把DA_C 改成DA_CR
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW
LABEL_DESC_DATA: Descriptor 0, DataLen -1,DA_DRW
LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32
LABEL_DESC_NORMAL:Descriptor 0, 0ffffh, DA_DRW
LABEL_DESC_CODE16:Descriptor 0, Code16Len - 1,DA_C
LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW
LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 1023, DA_DRW | DA_LIMIT_4K
;LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 4096 * 8 - 1, DA_DRW ; Page Tables
LABEL_DESC_FLAT_C: Descriptor 0, 0fffffh, DA_CR | DA_32 |DA_LIMIT_4K
LABEL_DESC_FLAT_RW: Descriptor 0, 0fffffh, DA_DRW | DA_LIMIT_4K
;GDT END
PageDirBase equ 200000h;页目录开始的地址:2MB
PageTblBase equ 201000h;页表开始地址:2MB + 4KB
GdtLen equ $ -LABEL_GDT
GdtPtr dw GdtLen - 1
dd 0
;GDT选择子
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
SelectorData equ LABEL_DESC_DATA - LABEL_GDT
SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT
SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT
SelectorPageDir equ LABEL_DESC_PAGE_DIR - LABEL_GDT
SelectorPageTbl equ LABEL_DESC_PAGE_TBL - LABEL_GDT
SelectorFlatC equ LABEL_DESC_FLAT_C - LABEL_GDT
SelectorFlatRW equ LABEL_DESC_FLAT_RW - LABEL_GDT
;END OF [SECTION .gdt]
[SECTION .data1]
LABEL_DATA:
SPValueInRealMode dw 0
PMMessage: db "In protect mode now ^_^",0
OffsetPMMessage equ PMMessage -$$
StrTest: db "ABCDEFGHIJKLMNOPQRSTUVWSYZ",0
OffsetStrTest equ StrTest - $$
; 实模式下使用这些符号
; 字符串
_szPMMessage: db "In Protect Mode now. ^-^", 0Ah, 0Ah, 0 ; 进入保护模式后显示此字符串
_szMemChkTitle: db "BaseAddrL BaseAddrH LengthLow LengthHigh Type", 0Ah, 0 ; 进入保护模式后显示此字符串
_szRAMSize db "RAM size:", 0
_szReturn db 0Ah, 0
; 变量
_wSPValueInRealMode dw 0
_dwMCRNumber: dd 0 ; Memory Check Result
_dwDispPos: dd (80 * 6 + 0) * 2 ; 屏幕第 6 行, 第 0 列。
_dwMemSize: dd 0
_ARDStruct: ; Address Range Descriptor Structure
_dwBaseAddrLow: dd 0
_dwBaseAddrHigh: dd 0
_dwLengthLow: dd 0
_dwLengthHigh: dd 0
_dwType: dd 0
_PageTableNumber dd 0
_MemChkBuf: times 256 db 0
; 保护模式下使用这些符号 地址只使用于实模式,在保护模式下,数据地址应该是其相对于段基址的偏移。
szPMMessage equ _szPMMessage - $$
szMemChkTitle equ _szMemChkTitle - $$
szRAMSize equ _szRAMSize - $$
szReturn equ _szReturn - $$
dwDispPos equ _dwDispPos - $$
dwMemSize equ _dwMemSize - $$
dwMCRNumber equ _dwMCRNumber - $$
ARDStruct equ _ARDStruct - $$
dwBaseAddrLow equ _dwBaseAddrLow - $$
dwBaseAddrHigh equ _dwBaseAddrHigh - $$
dwLengthLow equ _dwLengthLow - $$
dwLengthHigh equ _dwLengthHigh - $$
dwType equ _dwType - $$
MemChkBuf equ _MemChkBuf - $$
PageTableNumber equ _PageTableNumber- $$
DataLen equ $ - LABEL_DATA
;END OF [SECTION .DATA1]
[SECTION .gs]
ALIGN 32
[BITS 32]
LABEL_STACK:
times 512 db 0
TopOfStack equ $ - LABEL_STACK - 1
[SECTION .s16];漏掉了.后面的s
[BITS 16]
LABEL_BEGIN:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h
mov [LABEL_GO_BACK_TO_REAL+3], ax
mov [_wSPValueInRealMode], sp
;得到内存数 也应该注意这段代码的位置问题
mov ebx, 0
mov di, _MemChkBuf
.loop:
mov eax, 0E820h
mov ecx, 20
mov edx, 0534D4150h
int 15h
jc LABEL_MEM_CHK_FAIL
add di, 20
inc dword [_dwMCRNumber]
cmp ebx, 0 ;放置着为等到下一个地址描述符所需要的后续值,通过它获取下一个地址范围描述符。
; 如果它的值为0,并且CF没有进位,表示它最后一个地址范围描述符
jne .loop
jmp LABEL_MEN_CHK_OK
LABEL_MEM_CHK_FAIL:
mov dword [_dwMCRNumber], 0
LABEL_MEN_CHK_OK:
;初始化32位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE32 ;加偏移加错了
mov word [LABEL_DESC_CODE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE32+4], al
mov byte [LABEL_DESC_CODE32+7], ah
;初始化数据段描述符
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_DATA
mov word [LABEL_DESC_DATA + 2], ax
shr eax, 16
mov byte [LABEL_DESC_DATA+4], al
mov byte [LABEL_DESC_DATA+7], ah
;Iinit code 16
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE16
mov word [LABEL_DESC_CODE16 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE16 + 4], al
mov byte [LABEL_DESC_CODE16 + 7], ah
;Iinit STACK
xor eax, eax
mov ax, ss
shl eax, 4
add eax, LABEL_STACK
mov word [LABEL_DESC_STACK + 2], ax
shr eax, 16
mov byte [LABEL_DESC_STACK + 4], al
mov byte [LABEL_DESC_STACK + 7], ah
;Init NORMAL
;加载gdtr做准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT
mov dword [GdtPtr+2], eax ;忘记+2
lgdt [GdtPtr]
cli
in al, 92h
or al,00000010b
out 92h, al
mov eax, cr0
or eax, 1
mov cr0, eax
jmp dword SelectorCode32:0
[SECTION .s32]
[BITS 32]
LABEL_SEG_CODE32:
mov ax, SelectorData
mov ds, ax
mov ax, SelectorData
mov es, ax
mov ax, SelectorVideo
mov gs, ax
mov ax, SelectorStack
mov ss, ax
mov esp, TopOfStack
push szPMMessage
call DispStr
add esp, 4
push szMemChkTitle
call DispStr
add esp, 4
call DispMemSize
call PagingDemo ; 启动分页机制
jmp SelectorCode16:0
SetupPaging:
; 根据内存大小计算应初始化多少PDE以及多少页表
xor edx, edx
mov eax, [dwMemSize]
mov ebx, 400000h ; 400000h = 4M = 4096 * 1024, 一个页表对应的内存大小
div ebx
mov ecx, eax ; 此时 ecx 为页表的个数,也即 PDE 应该的个数
test edx, edx
jz .no_remainder
inc ecx ; 如果余数不为 0 就需增加一个页表
.no_remainder:
mov [PageTableNumber], ecx ; 暂存页表个数
; 为简化处理, 所有线性地址对应相等的物理地址. 并且不考虑内存空洞.
; 首先初始化页目录
mov ax, SelectorFlatRW
mov es, ax
mov edi, PageDirBase0 ; 此段首地址为 PageDirBase0
xor eax, eax
mov eax, PageTblBase0 | PG_P | PG_USU | PG_RWW
.1:
stosd
add eax, 4096 ; 为了简化, 所有页表在内存中是连续的.
loop .1
; 再初始化所有页表
mov eax, [PageTableNumber] ; 页表个数
mov ebx, 1024 ; 每个页表 1024 个 PTE
mul ebx
mov ecx, eax ; PTE个数 = 页表个数 * 1024
mov edi, PageTblBase0 ; 此段首地址为 PageTblBase0
xor eax, eax
mov eax, PG_P | PG_USU | PG_RWW
.2:
stosd
add eax, 4096 ; 每一页指向 4K 的空间
loop .2
mov eax, PageDirBase0
mov cr3, eax
mov eax, cr0
or eax, 80000000h
mov cr0, eax
jmp short .3
.3:
nop
ret
; 分页机制启动完毕 ----------------------------------------------------------
;新增的DispMemSize
DispMemSize:
push esi
push edi
push ecx
mov esi, MemChkBuf
mov ecx, [dwMCRNumber]
.loop:
mov edx, 5
mov edi, ARDStruct
.1:
push dword [esi]
call DispInt
pop eax
stosd
add esi, 4
dec edx
cmp edx, 0
jnz .1
call DispReturn
cmp dword [dwType], 1
jne .2
mov eax, [dwBaseAddrLow]
add eax, [dwLengthLow]
cmp eax, [dwMemSize]
jb .2
mov [dwMemSize], eax
.2:
loop .loop
call DispReturn
push szRAMSize
call DispStr
add esp, 4
push dword [dwMemSize]
call DispInt
add esp, 4
pop ecx
pop edi
pop esi
ret
;********************
;PagingDemo
PagingDemo:
mov ax, cs
mov ds, ax
mov ax, SelectorFlatRW
mov es, ax
push LenFoo
push OffsetFoo
push ProcFoo
call MemCpy
add esp, 12
push LenBar
push OffsetBar
push ProcBar
call MemCpy
add esp, 12
push LenPagingDemoAll
push OffsetPagingDemoProc
push ProcPagingDemo
call MemCpy
add esp, 12
mov ax, SelectorData
mov ds, ax
mov es, ax
call SetupPaging ;启动分页
call SelectorFlatC: ProcPagingDemo
call PSwitch
call SelectorFlatC: ProcPagingDemo
ret
;*************************
;PagingDemoProc
PagingDemoProc:
OffsetPagingDemoProc equ PagingDemoProc - $$
mov eax, LinearAddrDemo
call eax
retf
LenPagingDemoAll equ $ - PagingDemoProc
;******************************************
;foo
foo:
OffsetFoo equ foo - $$
mov ah, 0Ch
mov al, 'F'
mov [gs: ((80*17 + 0)*2)], ax
mov al, 'o'
mov [gs:((80*17+1)*2)], ax
mov [gs:((80*17+2)*2)], ax
ret
LenFoo equ $ - foo
;*******************************************
;bar
bar:
OffsetBar equ bar - $$
mov ah, 0Ch
mov al, 'B'
mov [gs:((80*18+0)*2)], ax
mov al, 'a'
mov [gs:((80*18+1)*2)], ax
mov al, 'r'
mov [gs:((80*18+2)*2)], ax
ret
LenBar equ $ - bar
;*************************************
;PSwitch
;初始化页目录
PSwitch:
mov ax, SelectorFlatRW
mov es, ax
mov edi, PageDirBase1
xor eax, eax
mov eax, PageTblBase1 |PG_P|PG_USU|PG_RWW
mov ecx, [PageTableNumber] ;把eax写成了ecx
.1:
stosd
add eax, 4096
loop .1
;初始化所有页表
mov eax, [PageTableNumber]
mov ebx, 1024
mul ebx
mov ecx, eax
mov edi, PageTblBase1
xor eax, eax
mov eax, PG_P |PG_USU | PG_RWW
.2:
stosd
add eax, 4096
loop .2
mov eax, LinearAddrDemo
shr eax, 22
mov ebx, 4096
mul ebx
mov ecx, eax
mov eax, LinearAddrDemo
shr eax, 12
and eax, 03FFh
mov ebx, 4
mul ebx
add eax, ecx
add eax, PageTblBase1
mov DWORD [es:eax],ProcBar | PG_P |PG_USU | PG_RWW
mov eax, PageDirBase1
mov cr3, eax
jmp short .3
.3:
nop
ret
%include "lib.inc" ; 库函数
SegCode32Len equ $ - LABEL_SEG_CODE32 ;上面的子程序不能放到其他位置,为什么呢?
;END OF[SECTION .S32]
[SECTION .s16code]
ALIGN 32
[BITS 16]
LABEL_SEG_CODE16:
mov ax, SelectorNormal
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and al, 11111110b
mov cr0, eax
LABEL_GO_BACK_TO_REAL:
jmp 0:LABEL_REAL_ENTRY
Code16Len equ $ - LABEL_SEG_CODE16
[SECTION .real]
[BITS 16]
LABEL_REAL_ENTRY:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, [_wSPValueInRealMode]
in al, 92h
and al, 11111101b
out 92h, al
sti
mov ax, 4c00h
int 21h
;REAL END
;***************
- 3.3.7进一步体会分页机制
- 一个操作系统的实现(8)-进一步体会分页机制
- 进一步体会到面对对象
- 进一步了解Flash坐标机制
- 对内存机制进一步理解
- 应用程序签名机制进一步说明
- 速算24点 深搜的进一步体会
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 分页机制
- 上交所:将进一步研究熔断机制
- 基于.NET平台的分层架构实战(十一)—表示层的实现
- 使用XML的五种场合
- C++中对象的大小
- 前置自动升级程序
- Visio 2003 sp3下载
- 3.3.7进一步体会分页机制
- 微软雅黑和微软雅黑Bold V5.00用于Windows XP
- 通用数据权限管理系统设计
- J2EE程序员需掌握的技术
- 调试技巧 之调用堆栈
- .net中保存用户信息的九种方法
- 会议录资源使用指南
- How To Configure IIS 6.0 and Tomcat with the JK 1.2 Connector
- 双绞线接法简介