我们在操作系统教科书上看到,对内存进行分页管理可以实现虚拟内存,这样对每一个进程来说,假如是32位的处理器,就有4G的内存空间。进程调度时,每调度一个进程,就切换到该进程的页表,就是给CR3赋一个对应的值就好。
下面的程序中,就是稍微模拟一下这种情况,建立两个页表,在相同的虚拟地址上改变另一个页表的映射,使其指向另一个函数,下面是代码:
lib.inc:
- Disp_Int:
- push ebp
- mov ebp,esp
- push eax
- push ecx
- push edi
- mov eax,[ebp + 8]
- mov ecx,4
- .1:
- rol eax,8
- call Disp_Al
- loop .1
- mov edi,[d_Disp_Pos]
- mov ah,7h
- mov al,'h'
- mov [gs:edi],ax
- add edi,2
- mov [d_Disp_Pos],edi
- pop edi
- pop ecx
- pop eax
- pop ebp
- ret
- Disp_Str:
- push ebp
- mov ebp,esp
- push eax
- push ebx
- push esi
- push edi
- mov esi,[ebp + 8]
- mov edi,[d_Disp_Pos]
- mov ah,0fh
- .1:
- lodsb
- test al,al
- jz .2
- cmp al,0ah
- jne .3
- mov eax,edi
- mov bl,160
- div bl
- and ax,0ffh
- inc ax
- mov bl,160
- mul bl
- mov edi,eax
- jmp .1
- .3:
- mov [gs:edi],ax
- add edi,2
- jmp .1
- .2:
- mov [d_Disp_Pos],edi
- pop edi
- pop esi
- pop ebx
- pop eax
- pop ebp
- ret
- Disp_Al:
- push ebp
- mov ebp,esp
- push esi
- push ecx
- push eax
- mov ecx,2
- shr al,4
- .3:
- and al,0fh
- cmp al,9
- jbe .1
- add al,7
- .1:
- add al,30h
- mov esi,[d_Disp_Pos]
- mov byte [gs:esi],al
- mov byte [gs:esi + 1],0fh
- add dword [d_Disp_Pos],2
- dec ecx
- cmp ecx,0
- je .2
- pop eax
- jmp .3
- .2:
- pop ecx
- pop esi
- pop ebp
- ret
- Disp_Return:
- push sz_Return
- call Disp_Str
- add esp,4
- ret
- Disp_Space:
- push sz_Space
- call Disp_Str
- add esp,4
- ret
- Memory_Copy:
- ;proto:
- ;void Memory_Copy(void *p_src,void *p_des,int len);
- push ebp
- mov ebp,esp
- push eax
- push ecx
- push esi
- push edi
- mov ecx,[ebp + 16]
- mov edi,[ebp + 12]
- mov esi,[ebp + 8]
- .1:
- mov al,[ds:esi]
- mov [es:edi],al
- inc esi
- inc edi
- loop .1
- pop edi
- pop esi
- pop ecx
- pop eax
- pop ebp
- ret
pm15.asm:
- %include "pm.inc"
- Page_Dir_Base1 equ 200000h
- Page_Tbl_Base1 equ 201000h
- Page_Dir_Base2 equ 210000h
- Page_Tbl_Base2 equ 211000h
- Proc_Paging_Demo equ 301000h
- Linear_Addr equ 401000h
- Proc_A equ 401000h
- Proc_B equ 501000h
- org 0100h
- jmp LABEL_BEGIN
- [section .gdt]
- LABEL_DESC_DUMMY:
- Descriptor 0,0,0
- LABEL_DESC_CODE32:
- Descriptor 0,GDT_Code32_Len - 1,DA_CR + DA_32
- LABEL_DESC_CODE16:
- Descriptor 0,GDT_Code16_Len - 1,DA_C
- LABEL_DESC_VIDEO:
- Descriptor 0b8000h,0ffffh,DA_DRW
- LABEL_DESC_DATA:
- Descriptor 0,Data_Len - 1,DA_DRW
- LABEL_DESC_STACK32:
- Descriptor 0,Stack_Len - 1,DA_DRW + DA_32
- LABEL_DESC_NORMAL:
- Descriptor 0,0ffffh,DA_DRW
- LABEL_DESC_FLAT_C:
- Descriptor 0,0fffffh,DA_C + DA_32 + DA_LIMIT4K
- LABEL_DESC_FLAT_RW:
- Descriptor 0,0fffffh,DA_DRW + DA_LIMIT4K
- GDT_Len equ $ - LABEL_DESC_DUMMY
- GDT_Ptr:
- dw GDT_Len - 1
- dd 0
- Selector_Code32 equ LABEL_DESC_CODE32 - LABEL_DESC_DUMMY
- Selector_Code16 equ LABEL_DESC_CODE16 - LABEL_DESC_DUMMY
- Selector_Video equ LABEL_DESC_VIDEO - LABEL_DESC_DUMMY
- Selector_Data equ LABEL_DESC_DATA - LABEL_DESC_DUMMY
- Selector_Stack32 equ LABEL_DESC_STACK32 - LABEL_DESC_DUMMY
- Selector_Normal equ LABEL_DESC_NORMAL - LABEL_DESC_DUMMY
- Selector_Flat_C equ LABEL_DESC_FLAT_C - LABEL_DESC_DUMMY
- Selector_Flat_RW equ LABEL_DESC_FLAT_RW - LABEL_DESC_DUMMY
- [section .stack32]
- [bits 32]
- LABEL_STACK32:
- times 512 db 0
- Stack_Len equ $ - $$
- [section .data]
- LABEL_DATA:
- _d_Disp_Pos dd 160 * 5
- d_Disp_Pos equ _d_Disp_Pos - $$
- _w_SP_Value_In_Real_Mode dw 0
- w_SP_Value_In_Real_Mode equ _w_SP_Value_In_Real_Mode - $$
- _sz_Memory_Info_Title db 'BaseAddrL BaseAddrH LengthLow LengthHigh Type',0
- sz_Memory_Info_Title equ _sz_Memory_Info_Title - $$
- _sz_Ram_Size db 'RAM SIZE:',0
- sz_Ram_Size equ _sz_Ram_Size - $$
- _sz_Return db 0ah,0
- sz_Return equ _sz_Return - $$
- _sz_Space db 20h,0
- sz_Space equ _sz_Space - $$
- _Memory_Info_Buffer times 256 db 0
- Memory_Info_Buffer equ _Memory_Info_Buffer - $$
- _d_Memory_Info_Num dd 0
- d_Memory_Info_Num equ _d_Memory_Info_Num - $$
- _ARDStruct:
- _d_Base_Addr_Low dd 0
- _d_Base_Addr_High dd 0
- _d_Length_Low dd 0
- _d_Length_High dd 0
- _d_Type dd 0
- ARDStruct equ _ARDStruct - $$
- d_Base_Addr_Low equ _d_Base_Addr_Low - $$
- d_Base_Addr_High equ _d_Base_Addr_High - $$
- d_Length_Low equ _d_Length_Low - $$
- d_Length_High equ _d_Length_High - $$
- d_Type equ _d_Type - $$
- _d_Ram_Size dd 0
- d_Ram_Size equ _d_Ram_Size - $$
- _d_Page_Table_Num dd 0
- d_Page_Table_Num equ _d_Page_Table_Num - $$
- Data_Len equ $ - $$
- [section .s16]
- [bits 16]
- LABEL_BEGIN:
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov ax,ss
- mov sp,0100h
- mov [LABEL_GO_BACK_TO_REAL + 3],ax
- mov ebx,0
- mov di,_Memory_Info_Buffer
- mov ecx,20
- mov edx,0534d4150h
- .loop:
- mov eax,0e820h
- int 15h
- jc LABEL_MEMORY_CHK_FAIL
- inc dword [_d_Memory_Info_Num]
- add di,20
- cmp ebx,0
- jne .loop
- jmp LABEL_MEMORY_OK
- LABEL_MEMORY_CHK_FAIL:
- mov dword [_d_Memory_Info_Num],0
- LABEL_MEMORY_OK:
- Fill_Descriptor LABEL_DESC_CODE32,LABEL_CODE32
- Fill_Descriptor LABEL_DESC_CODE16,LABEL_BEGIN
- Fill_Descriptor LABEL_DESC_DATA,LABEL_DATA
- Fill_Descriptor LABEL_DESC_STACK32,LABEL_STACK32
- xor eax,eax
- mov ax,ds
- shl eax,4
- add eax,LABEL_DESC_DUMMY
- mov dword [GDT_Ptr + 2],eax
- lgdt [GDT_Ptr]
- mov [w_SP_Value_In_Real_Mode],sp
- cli
- in al,92h
- or al,00000010b
- out 92h,al
- mov eax,cr0
- or al,1
- mov cr0,eax
- jmp dword Selector_Code32:0
- _LABEL_PREPARE_GO_BACK_TO_REAL:
- LABEL_PREPARE_GO_BACK_TO_REAL equ _LABEL_PREPARE_GO_BACK_TO_REAL - $$
- mov ax,Selector_Normal
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov gs,ax
- mov fs,ax
- mov eax,cr0
- and eax,7ffffffeh
- mov cr0,eax
- LABEL_GO_BACK_TO_REAL:
- jmp 0:LABEL_ALREADY_REAL
- LABEL_ALREADY_REAL:
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov sp,[w_SP_Value_In_Real_Mode]
- mov fs,ax
- mov gs,ax
- in al,92h
- and al,11111101b
- out 92h,al
- in al,92h
- and al,11111101b
- out 92h,al
- sti
- mov ax,4c00h
- int 21h
- GDT_Code16_Len equ $ - $$
- [section .s32]
- [bits 32]
- LABEL_CODE32:
- mov ax,Selector_Stack32
- mov ss,ax
- mov esp,Stack_Len
- mov ax,Selector_Video
- mov gs,ax
- mov ax,Selector_Data
- mov ds,ax
- mov es,ax
- call Disp_Memory_Info
- call Paging_Demo
- jmp Selector_Code16:LABEL_PREPARE_GO_BACK_TO_REAL
- Paging_Demo:
- mov ax,Selector_Code32
- mov ds,ax
- mov ax,Selector_Flat_RW
- mov es,ax
- push Paging_Demo_Proc_Len
- push Proc_Paging_Demo
- push Paging_Demo_Proc
- call Memory_Copy
- add esp,12
- push A_Proc_Len
- push Proc_A
- push A_Proc
- call Memory_Copy
- add esp,12
- push B_Proc_Len
- push Proc_B
- push B_Proc
- call Memory_Copy
- add esp,12
- mov ax,Selector_Data
- mov ds,ax
- mov ax,Selector_Flat_RW
- mov es,ax
- call Setup_Paging
- call Selector_Flat_C:Proc_Paging_Demo
- call Page_Switch
- call Selector_Flat_C:Proc_Paging_Demo
- ret
- Disp_Memory_Info:
- push eax
- push ecx
- push edx
- push esi
- push edi
- push sz_Memory_Info_Title
- call Disp_Str
- add esp,4
- call Disp_Return
- mov ecx,[d_Memory_Info_Num]
- mov esi,Memory_Info_Buffer
- .1:
- mov edx,5
- mov edi,ARDStruct
- .2:
- push dword [esi]
- call Disp_Int
- pop eax
- stosd
- add esi,4
- call Disp_Space
- call Disp_Space
- dec edx
- cmp edx,0
- jne .2
- cmp dword [d_Type],1
- jne .3
- mov eax,[d_Base_Addr_Low]
- add eax,[d_Length_Low]
- cmp eax,[d_Ram_Size]
- jb .3
- mov [d_Ram_Size],eax
- .3:
- call Disp_Return
- loop .1
- push sz_Ram_Size
- call Disp_Str
- add esp,4
- push dword [d_Ram_Size]
- call Disp_Int
- add esp,4
- pop edi
- pop esi
- pop edx
- pop ecx
- pop eax
- ret
- Setup_Paging:
- push eax
- push ebx
- push ecx
- push edx
- push edi
- xor edx,edx
- mov eax,[d_Ram_Size]
- mov ebx,1024 * 1024 * 4
- div ebx
- test edx,edx
- jz .skip
- inc eax
- .skip:
- mov [d_Page_Table_Num],eax
- mov ecx,eax
- mov eax,Page_Tbl_Base1 + 7h
- mov edi,Page_Dir_Base1
- .1:
- stosd
- add eax,4096
- loop .1
- mov eax,[d_Page_Table_Num]
- mov ebx,1024
- mul ebx
- mov ecx,eax
- mov eax,7h
- mov edi,Page_Tbl_Base1
- .2:
- stosd
- add eax,4096
- loop .2
- mov eax,Page_Dir_Base1
- mov cr3,eax
- mov eax,cr0
- or eax,80000000h
- mov cr0,eax
- pop edi
- pop edx
- pop ecx
- pop ebx
- pop eax
- ret
- Page_Switch:
- push eax
- push ebx
- push ecx
- push edx
- push edi
- mov ecx,[d_Page_Table_Num]
- mov eax,Page_Tbl_Base2 + 7h
- mov edi,Page_Dir_Base2
- .1:
- stosd
- add eax,4096
- loop .1
- mov eax,[d_Page_Table_Num]
- mov bx,1024
- mul bx
- mov ecx,eax
- mov eax,7h
- mov edi,Page_Tbl_Base2
- .2:
- stosd
- add eax,4096
- loop .2
- mov eax,Linear_Addr
- shr eax,22
- and eax,3ffh
- mov bx,4
- mul bx
- mov ecx,eax
- mov ecx,[es:Page_Dir_Base2 + ecx]
- and ecx,0fffffc00h
- mov eax,Linear_Addr
- shr eax,12
- and eax,3ffh
- mov bx,4
- mul bx
- add ecx,eax
- push ecx
- call Disp_Int
- add esp,4
- mov dword [es:ecx],Proc_B + 7h
- mov edx,[es:ecx]
- mov eax,Page_Dir_Base2
- mov cr3,eax
- pop edi
- pop edx
- pop ecx
- pop ebx
- pop eax
- ret
- _Paging_Demo_Proc:
- Paging_Demo_Proc equ _Paging_Demo_Proc - $$
- mov eax,Linear_Addr
- call eax
- retf
- Paging_Demo_Proc_Len equ $ - _Paging_Demo_Proc
- _A_Proc:
- A_Proc equ _A_Proc - $$
- mov ah,0ch
- mov al,'A'
- mov [gs:160 * 16],ax
- ret
- A_Proc_Len equ $ - _A_Proc
- _B_Proc:
- B_Proc equ _B_Proc - $$
- mov ah,0ch
- mov al,'B'
- mov [gs:160 * 17],ax
- ret
- B_Proc_Len equ $ - _B_Proc
- %include "lib.inc"
- GDT_Code32_Len equ $ - $$
运行结果如图: