.386p
.model flat,stdcall
include win32.inc
extrn ExitProcess:PROC
extrn MessageBoxA:PROC
extrn _wsprintfA:PROC
CALL32 MACRO selector ,offsetv
DB 09AH
DD offsetv
DW selector
ENDM
LinearAddr equ offset Start ;要查看的线性地址
.data
PhysAddr dd ? ;存放得到的物理地址
User db 'User',0
System db 'System',0
Read db 'Read',0
Write db 'Write',0
Caption db '线性地址到物理地址的转换',0
Text db 150 dup (0)
ErrParam db '线性地址 %8XH 不在内存中!',0
SucParam db '线性地址:%8XH',0dh,0ah
db '物理地址:%8XH',0Dh,0Ah
db '页属性:%s/%s',0
.code
Start:
call ToRing0Code,offset L2P ;取物理地址及页信息
call Show ;显示物理地址及页信息
call ExitProcess,0 ;退出进程
Show Proc
test eax,1 ;存在否?
jnz Present
call _wsprintfA,offset Text,offset ErrParam,LinearAddr
add esp,4*3
call MessageBoxA,0,offset Text,offset Caption,MB_OK
call ExitProcess,1
Present:
mov esi,offset User
mov edi,offset Read
test eax,100B ;用户页还是系统页?
jnz Usr
mov esi,offset System
Usr:test eax,10B ;只读还是可写?
jz RD
mov edi,offset Write
RD: call _wsprintfA,offset Text,offset SucParam,LinearAddr,[PhysAddr],esi,edi
add esp,4*6
call MessageBoxA,0,offset Text,offset Caption,MB_OK
ret
Show endp
ToRing0Code proc Ring0Proc:DWORD ;生成调用门并调用Ring0子程序Ring0Proc
LOCAL Temp,Temp1
call GetLdtAddress ;取出LDT的地址,返回结果在eax中
mov ecx,[eax] ;保存LDT第一个描述符
mov [Temp],ecx ;
mov ecx,[eax+4] ;
mov [Temp1],ecx ;
mov edx,Ring0Proc ;把调用门的内容写入LDT
mov [eax],dx ;偏移量的低16位
mov word ptr [eax+2],28h ;段选择子
mov word ptr [eax+4],0ec00h ;属性
shr edx,16 ;偏移量的高16位
mov [eax+6],dx ;
push eax
CALL32 7,0 ;调用 Ring0 子程序
pop ebx
mov edx,[Temp] ;恢复LDT第一个描述符
mov [ebx],edx ;
mov edx,[Temp1] ;
mov [ebx+4],edx ;
ret
ToRing0Code endp
GetLdtAddress proc ;取LDT的地址
push ebx ;先要取GDT的地址
sgdt [esp-2] ;
pop ebx ;
sldt ax ;取LDT内容
and eax,0fff8H ;屏蔽掉低3位、eax的高16位清0
add ebx,eax ;算出LDT描述符的位置
mov eax,[ebx+2] ;从描述符中取出LDT的地址
mov dl,[ebx+7] ;
shl edx,24 ;
and eax,0ffffffh ;
or eax,edx ;
ret
GetLdtAddress endp
L2P proc far ;Ring0程序,由线性地址取得物理地址及其页属性
mov eax,cr3 ;CR3是页表目录寄存器
push eax ;取页表目录的线性地址
call P2L ;
mov edx,LinearAddr ;取出线性地址
shr edx,22 ;取高10位
shl edx,2 ;乘4(每项4字节)
mov eax,[eax+edx] ;取对应页表的(物理)地址
test eax,1 ;存在否?
jz Quit
and eax,0fffff000H ;清除属性位
push eax ;取对应页表的线性地址
call P2L ;
mov edx,LinearAddr ;取线性地址第12-21位
shl edx,10 ;
shr edx,22 ;
shl edx,2 ;乘4
mov eax,[eax+edx] ;取出物理页地址
test eax,1 ;存在否?
jz Quit
push eax ;保存eax,用作返回值
and eax,0fffff000H ;填入页内偏移
mov edx,LinearAddr ;
and edx,00000FFFH ;
or eax,edx ;
mov [PhysAddr],eax ;保存好物理地址
pop eax ;返回对应的物理页和属性
Quit:
ret
L2P endp
P2L proc ,Physcial ;由物理地址得到线性地址
push Physcial
int 20H ;VxDCall _MapPhysToLinear
dd 0001006cH
add esp,4 ;调整堆栈
ret
P2L endp
END Start
- [younggay] 20? 那个20? 01/21 15:05
- [martian] 博主辛苦了! 11/24 13:43
- [acool] 先存下 看看O(∩_∩)O哈哈~ 11/22 12:30
- [acool] 不错,踩踩;) 11/22 12:27
- [tomato] 收藏一下,好好看看,扫扫盲。 11/21 20:01
- [younggay] 程序正确固然重要,必要的地方写注释也是很必要的。要不看的人脑袋可就大了。呵呵 fighting ! 11/21 14:47
- [younggay] 就提一点要求: 哥儿们,加点注释把,(*^__^*)...嘻嘻 11/21 14:37
- [lwbfq] 有点糊涂。 11/21 14:26
- [lwbfq] 有点糊涂。 11/21 14:26
- [younggay] 嗯。不错,不过要是关键代码部分加上注释就更好了。而且加注释也是一个成熟的编程人员的良好习惯。 11/21 14:23
- [h.goood] 汇编作业在哪里做?我怎么没找到? 11/24 12:32