• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開(kāi)心的工作
            簡(jiǎn)單、開(kāi)放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            操作系統(tǒng)中分頁(yè)管理內(nèi)核的模擬與實(shí)現(xiàn)

            ??

            ?現(xiàn)代操作系統(tǒng)大部分都采用了分頁(yè)的方式對(duì)物理內(nèi)存進(jìn)行管理,Intel 從80386之后也在硬件上支持的分頁(yè)管理,為操作系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)帶來(lái)了很多便利之處。
            ?由于實(shí)際去實(shí)現(xiàn)一個(gè)操作系統(tǒng)的內(nèi)存管理內(nèi)核是一件相對(duì)比較困難的事情,因此我們今天將用模擬的方式來(lái)設(shè)計(jì)和實(shí)現(xiàn)一個(gè)操作系統(tǒng)的分頁(yè)管理內(nèi)核。由于我自己也是一個(gè)學(xué)生,因此有說(shuō)的不妥甚至錯(cuò)誤的地方,請(qǐng)各位看官不要吝嗇您的意見(jiàn)建議甚至批評(píng)。如無(wú)特別說(shuō)明,下文的物理內(nèi)存地址一詞均指模擬物理內(nèi)存中的物理地址。
            一切開(kāi)始以前先來(lái)確定一些基準(zhǔn)數(shù)據(jù):
            1.?物理頁(yè)的大小:物理頁(yè)的大小通常和硬件系統(tǒng)有關(guān),

            2.?比如Intel80386及以后的處理器都是按4KB大小來(lái)分頁(yè)。這里我們也選擇用4KB來(lái)作為分頁(yè)的尺寸。
            3.?邏輯頁(yè)的大小:邏輯頁(yè)的大小個(gè)人認(rèn)為和物理頁(yè)取同4.?樣大小最好,5.?因?yàn)檫@樣可以不6.?用擔(dān)心頁(yè)邊界問(wèn)題,7.?并且在設(shè)計(jì)分頁(yè)變換機(jī)構(gòu)時(shí)比較容易實(shí)現(xiàn)。因此也取為4KB。
            8.?系統(tǒng)能有效管理的最大內(nèi)存:作為一個(gè)模擬系統(tǒng),9.?這里我取32MB作為最大內(nèi)存管理上限,10.?太大了沒(méi)什么實(shí)際意義,11.?再說(shuō)模擬系統(tǒng)跑起來(lái)也會(huì)很占資源。
            12.?頁(yè)號(hào)地址范圍:依照邏輯頁(yè)尺寸和支持的最大內(nèi)存,13.?系統(tǒng)中最多可有8192個(gè)邏輯頁(yè)面,14.?則頁(yè)面地址為0x0-0x1FFF
            15.?頁(yè)內(nèi)偏移量范圍:頁(yè)尺寸取為4KB 則頁(yè)內(nèi)偏移地址為0x0-0x0fff.。
            在分頁(yè)管理系統(tǒng)中,地址的通常不止一種。在我們現(xiàn)在要做的系統(tǒng)中,地址分為3類,既分頁(yè)地址,線性地址,虛擬地址。
            線性地址:線性地址既存儲(chǔ)器的物理地址,在系統(tǒng)內(nèi)核未初始化和初始化時(shí),都將使用線性地址操作內(nèi)存。
            虛擬地址:虛擬地址是在分頁(yè)后產(chǎn)生的。其含義和線形地址相同,在系統(tǒng)中存在的各個(gè)進(jìn)程,都使用虛擬地址訪問(wèn)內(nèi)存,虛擬地址傳入內(nèi)核后,內(nèi)核利用該進(jìn)程的頁(yè)表和自身的頁(yè)地址變換機(jī)構(gòu)將虛擬地址映射為某一個(gè)線性地址。
            分頁(yè)地址:分頁(yè)地址由2部分組成,按照上文的基準(zhǔn)數(shù)據(jù)設(shè)定,其結(jié)構(gòu)如下:
            ????BBBBBBBBBBBBB:BBBBBBBBBBBB
            ?前一部分共13bit用來(lái)記錄頁(yè)號(hào)地址,后一部分共12bit用來(lái)記錄頁(yè)內(nèi)偏移量。由于我們將物理頁(yè)和邏輯頁(yè)的尺寸統(tǒng)一了,因此分頁(yè)地址所表示的整體意義和線性地址是一樣的。
            例如:分頁(yè)地址0000000000001000000000001 是0x1001。作為分頁(yè)地址,它表示物理內(nèi)存中第二個(gè)物理頁(yè)(注意,不是第一個(gè)物理頁(yè),因?yàn)?x0000也是有效地址,表示的是第一個(gè)物理頁(yè)),頁(yè)內(nèi)偏移量為01。這個(gè)分頁(yè)地址所表示的線性地址為:頁(yè)號(hào)×頁(yè)尺寸+頁(yè)內(nèi)偏移量,即:1×4096+1=4097 (0x1001)。可以看到,從整體上來(lái)看,分頁(yè)地址和線性地址在意義上一樣的,但是分頁(yè)地址和線性地址所表示的自身含義則是完全不同的,這一點(diǎn)在邏輯頁(yè)和物理頁(yè)尺寸不統(tǒng)一的情況下尤為明顯,并且在這種情況下,分頁(yè)地址和線性地址的整體含義也就完全不同了。由此看出,邏輯頁(yè)和物理頁(yè)尺寸的統(tǒng)一給我們?cè)O(shè)計(jì)和實(shí)現(xiàn)內(nèi)核的地址變換部分提供了很大的便利。
            ?在正式開(kāi)始設(shè)計(jì)內(nèi)核前,先來(lái)看看現(xiàn)代操作系統(tǒng)的一個(gè)重要特征:硬件無(wú)關(guān)性。這個(gè)特征通常是提供給用戶的。但是個(gè)人認(rèn)為,在操作系統(tǒng)的底層設(shè)計(jì)中,也應(yīng)該有一個(gè)接口部分是直接操作硬件,而其他部分在這個(gè)部分之上,通過(guò)這個(gè)接口去訪問(wèn)和控制硬件。這樣做可以使得操作系統(tǒng)的實(shí)現(xiàn)可以在某種程度上脫離具體硬件規(guī)格,并且可以給移植帶來(lái)方便。這種設(shè)計(jì)思路在Microsoft Windows NT家族的中得到了具體的體現(xiàn),NT中使用了“硬件抽象層”(HAL)的概念來(lái)分離操作系統(tǒng)的相對(duì)高層部分和底層硬件。各個(gè)高層部分通過(guò)HAL層來(lái)訪問(wèn)和控制硬件,而不是將各種對(duì)硬件的訪問(wèn)和控制操作分散在系統(tǒng)的各個(gè)角落。這種設(shè)計(jì)思路將在我們今天即將開(kāi)始設(shè)計(jì)的模擬內(nèi)核中再一次得到體現(xiàn)。這就是“模擬硬件抽象層”(EmuHAL)。
            ?EmuHAL的設(shè)計(jì)思路完全取自Windows NT的HAL。作為給這個(gè)模擬內(nèi)核搭配的HAL層,EmuHAL將提供一個(gè)基本上完全真實(shí)的物理內(nèi)存環(huán)境供我們來(lái)操作,你可以認(rèn)為通過(guò)EmuHAL層進(jìn)行操作和訪問(wèn)的是完全的一個(gè)物理硬件,而不必要將其想象成別的什么。在這里,EmuHAL層通過(guò)利用一個(gè)數(shù)組,來(lái)提供真實(shí)的物理內(nèi)存操作環(huán)境。下面是其提供的接口函數(shù):

            DWORD? APIENTRY?Fn_HAL_Init(LPDWORD??lpMemoary,????
            UDWORD ??NewMemoaryLength);

            BYTE?APIENTRY?Fn_ReadByte(UDWORD Address);
            VOID?APIENTRY?Fn_WriteByte(UDWORD Address,DWORD Value);

            WORD?APIENTRY?Fn_ReadWord(UDWORD Address);
            VOID?APIENTRY?Fn_WriteWord(UDWORD Address,DWORD Value);

            DWORD?APIENTRY?Fn_ReadDword(UDWORD Address);
            VOID?APIENTRY?Fn_WriteDword(UDWORD Address,DWORD Value);

            這些函數(shù)都是對(duì)內(nèi)存的原子操作的模擬。除去第一初始化函數(shù)外,從上到下一共3組,每組對(duì)應(yīng)一個(gè)讀寫(xiě)服務(wù)集,分別為:字節(jié)讀/寫(xiě)集,字讀/寫(xiě)集, 雙字讀/寫(xiě)集。EmuHAL層的實(shí)現(xiàn)源代碼如下:
            宏定義頭文件::Base.h
            //=================================================================================
            //Name:??Base.h
            //Funcation:?Base Type Define,CPU support,MyUnicode Support.
            //Author:?kakashi.R
            //Last Update:?6.1.2005
            //=================================================================================?


            #ifndef _BASE_H
            #define?_BASE_H

            #define??TRUE??1
            #define??FALSE??0
            #define??SUCCESS??1
            #define??FAILURE??0
            #define??ENABLE??1
            #define??DISABLE??0
            #define??HIGH??1
            #define??LOW??0
            #define??USED??1
            #define??UNUSE??0
            #define??NULL??0

            #pragma message("")
            #pragma message("This is A Header File Created by kakashir. :)")
            #pragma message("")

            #if (defined _IOSTREAM)?? //Incude iostream.h for I/O.
            #pragma message("")
            #pragma?message("Macro _IOSTREAM actived Now.")
            #pragma message("Now iostream.h included for I/O.")
            #pragma?message("")
            #include <iostream.h>
            #endif? //#if (defined _IOSTREAM)


            #if ( !(defined APIENTRY) && (defined _STDAPI) ) //__stdcall style support.
            #pragma message("")
            #pragma message("Macro _STDAPI actived Now.")
            #pragma message("Funcations call style KeyWord APIENTRY Defined as __stdcall.")
            #pragma message("")
            #define??APIENTRY???__stdcall???
            #define??CENTRY????__cdecl????
            #define??API????APIENTRY???
            #define??PASCAL????API????
            #define??CALLBACK???PASCAL????
            #endif? //#if ( !(defined APIENTRY) && (defined _STDAPI) )

            #ifdef?_I386?? //Intel 80386 and later CPU support and typedefs.
            #pragma message("")
            #pragma message("Macro _I386 actived NOW.")
            #pragma message("Data define Keywords defined for Intel 80386 and later Processer Family.")
            #pragma message("")

            #if !(defined _UNICODE)
            typedef??char????CHAR;
            #endif? //#if !(defined _UNICODE )

            typedef??__int8????BYTE;
            typedef??__int16????WORD;
            typedef??__int32????DWORD;
            typedef??__int64????QWORD;
            typedef??float????FLOAT;
            typedef??double????DOUBLE;

            typedef??unsigned?__int8??UBYTE;
            typedef??unsigned?__int16??UWORD;
            typedef??unsigned?__int32??UDWORD;
            typedef??unsigned?__int64??UQWORD;

            typedef??void*????LPVOID;
            typedef??WORD*????LPWORD;
            typedef??BYTE*????LPBYTE;
            typedef??DWORD*????LPDWORD;
            typedef??QWORD*????LPQWORD;
            typedef??FLOAT*????LPFLOAT;
            typedef??DOUBLE*????LPDOUBLE;

            typedef??UBYTE*????LPUBYTE;
            typedef??UWORD*????LPUWORD;
            typedef??UDWORD*????LPUDWORD;
            typedef??UQWORD*????LPUQWORD;
            ????
            typedef??bool????BOOL;
            typedef??void????VOID;

            typedef?union?___uint128???? //128bit unsigned data support.
            {
            ?unsigned __int64??__128[2];
            ?unsigned __int32??__32[4];
            ?unsigned __int16??__16[8];
            ?unsigned __int8???__8[16];
            }uint128;

            typedef?union?___sint128??? //128bit signed data support.
            {
            ?signed __int64??__128[2];
            ?signed __int32??__32[4];
            ?signed __int16??__16[8];
            ?signed __int8??__8[16];
            }sint128;

            typedef??UBYTE????U8;
            typedef??short?unsigned??U16;
            typedef??long?unsigned??U32;
            typedef??UQWORD????U64;
            typedef??uint128????U128;

            typedef??BYTE????S8;
            typedef??short?signed???S16;
            typedef??long?signed???S32;
            typedef??QWORD????S64;
            typedef??sint128????S128;
            #endif ?//#ifdef? _I386


            #if (defined _UNICODE && defined _I386)? // MyUNICODE support!! :)
            #pragma message("")
            #pragma message("Macro _UNICODE actived NOW.")
            #pragma message("The Keyword CHAR(upcase) defined 16bit for support UNICODE now.")
            #pragma message("Pleas use cout() to display UNICODE char or String.")
            #pragma?message("use __char to define Old ANSCII-Style Character :)")
            #pragma message("")

            typedef?char?__char;

            typedef union?___wchar?? //Define MyUNICODE struct.
            {?
            ?U16?Unicode16;
            ?U8?Unicode8[2];
            }__wchar;

            typedef?? __wchar CHAR;

            #include <UnicodeTable.h>? //include MyUNICODE Table :)
            #define?__IOSTREAM
            #include <iostream.h>

            #if (defined _IOSTREAM)

            void APIENTRY?_cout(CHAR Word)? //MyUnicode I/O Funcation for character Display
            {
            ?if(Word.Unicode8[1] == 0)
            ??{
            ???cout<<(__char)Word.Unicode8[0]<<flush;
            ??}
            ?else
            ??{
            ???if(Word.Unicode8[1] >=0 && Word.Unicode8[1] <= HIGH_WORD_MAX &&
            ????? Word.Unicode8[0] >=0 && Word.Unicode8[0] <= LOW_WORD_MAX)
            ????{
            ?????_Buffer[0] = *(UnicodeTable[(Word.Unicode8[1]-1)] +?? (2*Word.Unicode8[0])?? );
            ?????_Buffer[1] = *(UnicodeTable[(Word.Unicode8[1]-1)] +?? (2*Word.Unicode8[0])+1 );
            ?????_Buffer[2] = '\0';
            ?????cout<<_Buffer<<flush;
            ????}
            ??}
            ?
            }
            void APIENTRY?_cout(CHAR* Word)? //MyUnicode I/O Funcation for String display
            {
            ?U32?Length = sizeof(Word)/2;
            ?U32?Tmp_a=0;
            ?for(Tmp_a=0;Tmp_a<Length;Tmp_a++)
            ??{
            ???if((Word+Tmp_a)->Unicode8[1] == 0)
            ????{
            ?????cout<<(__char)( (Word+Tmp_a)->Unicode8[0])<<flush;
            ????}
            ???else if ( ((Word+Tmp_a)->Unicode8[1]) >=0 && ((Word+Tmp_a)->Unicode8[1]) <= HIGH_WORD_MAX &&
            ???????????? ((Word+Tmp_a)->Unicode8[0]) >=0 && ((Word+Tmp_a)->Unicode8[0]) <= LOW_WORD_MAX )
            ?????{
            ??????_Buffer[0] = *(UnicodeTable[ ( (Word+Tmp_a)->Unicode8[1] )-1 ] + 2*( (Word+Tmp_a)->Unicode8[0] )? );
            ??????_Buffer[1] = *(UnicodeTable[ ( (Word+Tmp_a)->Unicode8[1] )-1 ] + 2*( (Word+Tmp_a)->Unicode8[0] )+1);
            ??????_Buffer[2] = '\0';
            ??????cout<<_Buffer<<flush;?????
            ?????}
            ??}
            }
            #define??lpUnicode(var,value)??((var)->Unicode16) = value
            #define??Unicode(var,value)??((var).Unicode16)? = value
            #define??cout(UnicodeString)??_cout(UnicodeString)?

            #endif? //#if (defined _IOSTREAM)?

            #endif //#if (define __UNICODE)

            #endif?? //#ifndef _BASE_H
            //===================================================================//
            EmuHAL層源代碼頭文件 Hal_Define.h
            #ifndef?_HAL_DEFINE_H
            #define?_HAL_DEFINE_H


            #define??_STDAPI
            #define??_I386
            #include?<base.h>

            #define??MAX_MEMOARY_SUPPORT?0x02000000

            DWORD?APIENTRY?Fn_HAL_Init(LPDWORD lpMemoary,UDWORD NewMemoaryLength);

            BYTE?APIENTRY?Fn_ReadByte(UDWORD Address);
            VOID?APIENTRY?Fn_WriteByte(UDWORD Address,DWORD Value);

            WORD?APIENTRY?Fn_ReadWord(UDWORD Address);
            VOID?APIENTRY?Fn_WriteWord(UDWORD Address,DWORD Value);

            DWORD?APIENTRY?Fn_ReadDword(UDWORD Address);
            VOID?APIENTRY?Fn_WriteDword(UDWORD Address,DWORD Value);

            #endif?//#ifndef?_HAL_DEFINE_H
            //===================================================================//
            EmuHAL 層源代碼實(shí)現(xiàn)文件:Hal.cpp
            #ifndef _HAL_H
            #define?_HAL_H
            #include "../include/HAL_Define.h"


            static?LPDWORD?lpMemoary=NULL;
            static?UDWORD?MemoarySize=NULL;

            DWORD?APIENTRY?Fn_HAL_Init(LPDWORD Init_lpMemoary,UDWORD NewMemoaryLength)
            {
            ?DWORD?Resault=SUCCESS;
            ?_asm
            ??{
            ???mov?EAX,[Init_lpMemoary]
            ???cmp?EAX,NULL
            ???je?ERROR
            ???mov?[lpMemoary],EAX
            ???jmp?EXIT?
            ??ERROR:
            ???mov?[Resault],FAILURE
            ??EXIT:?
            ???
            ??}
            ?MemoarySize = NewMemoaryLength;
            ?_asm
            ??{
            ???cmp?[MemoarySize],MAX_MEMOARY_SUPPORT
            ???ja?OverFlow
            ???jmp?OK
            ??OverFlow:
            ???mov?[MemoarySize],MAX_MEMOARY_SUPPORT
            ??OK:
            ??}
            ?return?Resault;
            }


            BYTE?APIENTRY?Fn_ReadByte(UDWORD Address)
            {
            ?BYTE?Resault=NULL;
            ?_asm
            ??{
            ????push?EBX
            ????
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????cmp?EBX,EAX
            ????jae?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????add?EBX,[Address]
            ????mov?BL ,BYTE ptr[EBX]
            ????mov?[Resault],BL
            ???EXIT:
            ????pop?EBX
            ??}
            ?
            ?return?Resault;
            }

            VOID?APIENTRY?Fn_WriteByte(UDWORD Address,DWORD Value)
            {
            ?_asm
            ??{
            ????push?EBX
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????cmp?EBX,EAX
            ????jae?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????mov?EAX,[Value]
            ????add?EBX,[Address]
            ????mov?BYTE ptr[EBX],AL
            ???EXIT:
            ????pop?EBX
            ??}
            }

            WORD?APIENTRY?Fn_ReadWord(UDWORD Address)
            {
            ?WORD?Resault=NULL;
            ?_asm
            ??{
            ????push?EBX
            ????
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????sub?EAX,0x02
            ????cmp?EBX,EAX
            ????ja?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????add?EBX,[Address]
            ????mov?BX ,WORD ptr[EBX]
            ????mov?[Resault],BX
            ???EXIT:
            ????pop?EBX
            ??}
            ?
            ?return?Resault;
            }

            VOID?APIENTRY?Fn_WriteWord(UDWORD Address,DWORD Value)
            {
            ?_asm
            ??{
            ????push?EBX
            ????
            ????
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????sub?EAX,0x02
            ????cmp?EBX,EAX
            ????ja?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????mov?EAX,[Value]
            ????add?EBX,[Address]
            ????mov?WORD ptr[EBX],AX
            ??
            ???EXIT:
            ????
            ????pop?EBX
            ??}

            }

            DWORD?APIENTRY?Fn_ReadDword(UDWORD Address)
            {
            ?DWORD?Resault=NULL;
            ?_asm
            ??{
            ????push?EBX
            ????
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????sub?EAX,0x04
            ????cmp?EBX,EAX
            ????ja?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????add?EBX,[Address]
            ????mov?EBX ,DWORD ptr[EBX]
            ????mov?[Resault],EBX
            ???EXIT:
            ????pop?EBX
            ??}
            ?
            ?return?Resault;
            }

            VOID?APIENTRY?Fn_WriteDword(UDWORD Address,DWORD Value)
            {
            ?_asm
            ??{
            ????push?EBX
            ????
            ????
            ????mov?EBX,[Address]
            ????mov?EAX,[MemoarySize]
            ????sub?EAX,0x04
            ????cmp?EBX,EAX
            ????ja?EXIT
            ????
            ????mov?EBX,[lpMemoary]
            ????mov?EAX,[Value]
            ????add?EBX,[Address]
            ????mov?DWORD ptr[EBX],EAX
            ??
            ???EXIT:
            ????
            ????pop?EBX
            ??}
            ??
            ?

            }
            #endif?//#ifndef _HAL_H???

            以上3個(gè)文件中,Base.h 是我個(gè)人給自己寫(xiě)的類型定義和宏定義文件。在后面設(shè)計(jì)實(shí)現(xiàn)內(nèi)核時(shí)也會(huì)用到。從現(xiàn)在開(kāi)始,我們正式進(jìn)入內(nèi)核的設(shè)計(jì)。
            ?首先,我們要實(shí)現(xiàn)的模擬內(nèi)核是內(nèi)存分頁(yè)管理內(nèi)核,但是由于分頁(yè)管理時(shí)有可能出現(xiàn)頁(yè)表過(guò)長(zhǎng)的情況(這在頁(yè)尺寸較小但需要管理的內(nèi)存總量很大時(shí)尤其明顯),這時(shí)我們采用的方法是將頁(yè)表分組,即多級(jí)頁(yè)表的方式。那么我們現(xiàn)在正在設(shè)計(jì)的模擬內(nèi)核也需要實(shí)現(xiàn)這樣的功能嗎?我個(gè)人給出的答案是否。并不是因?yàn)槲覀児芾淼淖畲髢?nèi)存只有32MB所以不需要這樣的功能,而是由我們所設(shè)計(jì)的模擬內(nèi)核在一個(gè)真實(shí)的操作系統(tǒng)所處的位置導(dǎo)致的。個(gè)人認(rèn)為,在真實(shí)的操作系統(tǒng)中,內(nèi)存管理內(nèi)核應(yīng)該并不是一個(gè)單獨(dú)整體,而是由一個(gè)層次結(jié)構(gòu)組成。大致上如下:

            ???????系統(tǒng)調(diào)用接口層
            ???????頁(yè)表管理層(高級(jí))
            ???????頁(yè)表管理層(低級(jí))
            ???????HAL層

            其中“頁(yè)表管理層(高級(jí))”部分實(shí)現(xiàn)對(duì)二級(jí)或者多級(jí)頁(yè)表的管理,而頁(yè)表管理層(低級(jí))部分則實(shí)現(xiàn)對(duì)于一級(jí)頁(yè)表中的地址映射,變換操作,同時(shí)由于該部分是緊挨HAL層的,因此對(duì)物理內(nèi)存的訪問(wèn)也將通過(guò)該層傳遞到HAL層。可能很多人要問(wèn),為什么不把對(duì)一級(jí)頁(yè)表的操作獨(dú)立出來(lái)呢?我是這樣考慮的,由于無(wú)論頁(yè)表是多級(jí)還是一級(jí),最終存放待映射地址的總是一級(jí)頁(yè)表,在訪問(wèn)到一級(jí)頁(yè)表后,緊接著馬上就要進(jìn)行對(duì)硬件的操作和訪問(wèn),因此為了高效,我將從一級(jí)頁(yè)表到傳遞給HAL操作的實(shí)現(xiàn)部分包含在了“頁(yè)表管理層(低級(jí))”中。現(xiàn)在我們就依照這樣的層次結(jié)構(gòu),來(lái)設(shè)計(jì)這個(gè)模擬內(nèi)核。以下是這個(gè)工程的名字和這個(gè)模擬內(nèi)核的代號(hào),在后文中,我可能將頻繁使用到這些代號(hào)。
            ?工程名:??操作系統(tǒng)中分頁(yè)管理內(nèi)核的模擬
            ?工程代號(hào):??EmuSolaris
            ?內(nèi)核代號(hào):??Venus

            我將采用C++來(lái)設(shè)計(jì)和實(shí)現(xiàn)這個(gè)模擬內(nèi)核,并且為了快速和方便,會(huì)使用一些asm指令,但是不會(huì)太復(fù)雜。
            ?作為操作系統(tǒng)中內(nèi)存管理內(nèi)核的最底層部分(僅高于HAL層),Venus必須明確知道其將要管理的硬件對(duì)象的具體參數(shù),在這里,就是物理內(nèi)存的尺寸,并且利用這個(gè)數(shù)據(jù),可以計(jì)算出系統(tǒng)中合法物理和邏輯頁(yè)面號(hào)的范圍。另外,在整個(gè)EmuSolaris中,Venus應(yīng)該是做為在HAL層被加載后首先被加載的內(nèi)核。在加載后,整個(gè)物理內(nèi)存的操作和訪問(wèn)都將由Venus去控制。并且在加載完后,分頁(yè)地址就應(yīng)該可以開(kāi)始使用,物理內(nèi)存也已經(jīng)被劃分為邏輯頁(yè)和物理頁(yè),并且可以開(kāi)始對(duì)物理內(nèi)存按頁(yè)為單位進(jìn)行分配和回收,提供給高層部分的內(nèi)存訪問(wèn)接口也已經(jīng)初始化完畢,可以利用指定的頁(yè)表對(duì)內(nèi)存進(jìn)行訪問(wèn)了。以上就是我認(rèn)為應(yīng)該最先設(shè)計(jì)并實(shí)現(xiàn)的基礎(chǔ)功能。相對(duì)的,Venus應(yīng)該有如下的數(shù)據(jù)結(jié)構(gòu)以用于支持分頁(yè)變換和地址映射功能。注意,這里所有的數(shù)據(jù)類型定義符都請(qǐng)參看前文的Base.h。
            BOOL?IsPage;???? //是否分頁(yè)管理 正常初始化時(shí)為1,即使用分頁(yè)管理
            ??UDWORD??PageAddressIndex;? //虛擬地址中的頁(yè)號(hào)地址?
            ??UDWORD??InPageOffset;??? //虛擬地址中的頁(yè)內(nèi)偏移地址
            ??UDWORD??NowLineAddress;??? //當(dāng)前等待變換或者使用的虛擬地址
            ??UDWORD??ErrorCode;????? //錯(cuò)誤代碼變量
            ??UDWORD??MemoarySize;??? //當(dāng)前總共內(nèi)存容量
            ??UDWORD??MaxPageIndex;?//最大頁(yè)面號(hào),有初始化時(shí)的總計(jì)內(nèi)存容量決定.
            為了實(shí)現(xiàn)上面所說(shuō)的基礎(chǔ)功能,Venus應(yīng)該具有如下的操作函數(shù):
            ??
            VOID?APIENTRY?Fn_TranslateLineAddress();
            ?VOID?APIENTRY?Fn_Service_LoadVirtualAddress(UDWORD VirtualAddress);
            VOID?APIENTRY?Fn_Service_Init(UDWORD?NewMemoarySize);

            Fn_Service_LoadVirtualAddress(UDWORD VirtualAddress)函數(shù)實(shí)現(xiàn)加載虛擬地址到Venus的操作。在上文中的數(shù)據(jù)結(jié)構(gòu)中,PageAddressIndex和InPageOffset分別用來(lái)保存當(dāng)前加載的虛擬地址中的頁(yè)號(hào)地址和頁(yè)內(nèi)偏移量地址。Fn_Service_LoadVirtualAddress函數(shù)就是對(duì)這個(gè)2個(gè)數(shù)據(jù)對(duì)象進(jìn)行操作。而Fn_TranslateLineAddress();則是執(zhí)行具體變換動(dòng)作的函數(shù),在IsPage為真的情況下,這個(gè)函數(shù)將會(huì)按照由Fn_Service_LoadVirtualAddress的參數(shù)傳遞過(guò)來(lái)的地址進(jìn)行變換,并將結(jié)果分別放在PageAddressIndex和InPageOffset中。而Fn_Service_LoadVirtualAddress中所帶的參數(shù)則會(huì)保存在NowLineAddress中。這個(gè)設(shè)計(jì)可以供以后在擴(kuò)展系統(tǒng)時(shí)使用。到這里,虛擬地址和線性地址轉(zhuǎn)換為分頁(yè)地址的操作就完成了。

            由于分頁(yè)管理的緣故,EmuSolaris中運(yùn)行的其他進(jìn)程都將使用虛擬地址來(lái)訪問(wèn)內(nèi)存,并且必須提供頁(yè)表以供Venus進(jìn)行從虛擬地址到物理地址的映射和變換。由此可以得到Venus的運(yùn)行圖:
            加載待讀取的虛擬地址à利用指定的頁(yè)表進(jìn)行地址變換,得到物理地址à將待訪問(wèn)的地址傳遞給EmuHAL層àEmuHAL層完成硬件操作
            按照這個(gè)運(yùn)行圖,可以看出,第一部分已經(jīng)設(shè)計(jì)完畢,那么我們首先來(lái)實(shí)現(xiàn)這個(gè)部分。代碼如下:

            首先是Venus啟動(dòng)和初始化函數(shù):
            VOID? APIENTRY?MemoaryKernel::Fn_Service_Init(UDWORD?NewMemoarySize)
            {
            ?MemoarySize = NewMemoarySize;
            ?InPageOffset = NULL;
            ?PageAddressIndex = NULL;
            ?NowLineAddress = NULL;
            ErrorCode = NORMAL;
            ?

            ?_asm//這段匯編完成計(jì)算出NewMemoarySize對(duì)應(yīng)的最大頁(yè)號(hào)地址
            ??{
            ???push?EDX
            ???push?ECX
            ???
            ???mov?EAX,[NewMemoarySize]
            ???mov?EDX,EAX
            ???and?EAX,0x0000FFFF
            ???
            ???shr?EDX,0x010
            ???and?EDX,0x0000FFFF
            ???
            ???mov?CX,0x01000
            ???div?CX

            ???sub?EAX,1

            ???and?EAX,0x0000FFFF

            ???mov?ECX,this
            ???mov?[ECX]this.MaxPageIndex,EAX
            pop?ECX
            ???pop?EDX
            ?}
            }
            //====================================================================//
            //加載虛擬/線性地址,以備進(jìn)行頁(yè)面地址變換操作:
            VOID?APIENTRY?MemoaryKernel::Fn_Service_LoadVirtualAddress(UDWORD VirtualAddress)
            {
            ?this->NowLineAddress = VirtualAddress;
            ?if (IsPage == TRUE) {Fn_TranslateLineAddress();}
            }
            //====================================================================//
            //執(zhí)行實(shí)際變換動(dòng)作的變換函數(shù):
            VOID?APIENTRY?MemoaryKernel::Fn_TranslateLineAddress()
            {?
            ?_asm
            ??{
            ???
            ???push?EBX
            ???push?ECX

            ???mov?EBX,this
            ???mov?EAX,[EBX]this.NowLineAddress
            ???mov?ECX,EAX

            ???and?EAX,0x0FFF //清空高24位得到頁(yè)內(nèi)偏移地址
            ???mov?[EBX]this.InPageOffset,EAX

            ???shr?ECX,12 //右移動(dòng)12位,得到頁(yè)號(hào)地址
            ???and?EAX,0x01FFF
            ???
            ???cmp?ECX,[EBX]this.MaxPageIndex
            ???jbe?OK
            ???mov?ECX,MAX_PAGE_NUMBER
            OK:
            ???mov?[EBX]this.PageAddressIndex,ECX
            ???pop?ECX
            ???pop?EBX
            ???
            ??}
            }
            //====================================================================//
            雖然完成了狀態(tài)圖上的第一部分功能,但是Venus目前仍然不具備對(duì)內(nèi)存進(jìn)行按頁(yè)分配和回收的功能。那么如何來(lái)設(shè)計(jì)這2個(gè)功能,是十分重要的,因?yàn)榉峙浜突厥帐荲enus的基礎(chǔ)的基礎(chǔ)功能。要分配和回收頁(yè)面,就需要了解整個(gè)物理內(nèi)存頁(yè)面的使用情況,最簡(jiǎn)單的辦法是采用位映射圖(BitMap)的數(shù)據(jù)結(jié)構(gòu)。BitMap,就是用一個(gè)bit位,來(lái)表示一個(gè)頁(yè)面的使用狀態(tài),只有1和0兩種狀態(tài),分別對(duì)應(yīng)頁(yè)面的 “已分配”(USED) 和“空閑”(UNUSE)2種狀態(tài)。但是,由于用來(lái)記錄內(nèi)存使用狀態(tài)的數(shù)據(jù)也是保存在內(nèi)存中的,那么,BitMap的空間效率如何呢?我們來(lái)計(jì)算一下:
            Venus最大支持32MB內(nèi)存,此時(shí)最大會(huì)有8192個(gè)頁(yè)面,也就是說(shuō),需要8192個(gè)bit來(lái)記錄內(nèi)存的使用狀態(tài),即8192bit/8 = 1024Byte =1KB空間。應(yīng)該說(shuō),BitMap的空間效率還是相當(dāng)不錯(cuò)的。那么這1KB的連續(xù)數(shù)據(jù)存放在物理內(nèi)存的什么地方呢?作為操作系統(tǒng)的內(nèi)核使用的數(shù)據(jù),我將它設(shè)計(jì)為存放在物理內(nèi)存的最低地址處,即 物理地址0x0-0x03fff。這樣的話,Venue中應(yīng)該新增加一個(gè)數(shù)據(jù)成員以記錄BitMap的存放的起始物理地址。我們新增加一個(gè)數(shù)據(jù)成員 _SaveLinerAddress 來(lái)記錄它:

            UDWORD??_SaveLinerAddress; //Map位圖存放的線性地址

            現(xiàn)在我們來(lái)設(shè)計(jì)下BitMap的細(xì)節(jié)部分,由于這個(gè)模擬程序是在Intel 80386以上的機(jī)器上編寫(xiě)的,因此為了實(shí)現(xiàn)bit操作時(shí)方便,我們將BitMap按32bit為一組進(jìn)行劃分。每組從右向左計(jì)數(shù)。對(duì)BitMap的操作集有2個(gè)函數(shù):設(shè)置函數(shù)和查詢函數(shù),其具體實(shí)現(xiàn)代碼將在最后給出。
            ?
            DWORD?APIENTRY?Fn_Service_SetBitMap(UDWORD? PageIndex,BOOL? Flag);
            ?????//設(shè)置位映射圖, 參數(shù)為分頁(yè)地址的頁(yè)號(hào).

            ?DWORD?APIENTRY?Fn_Service_GetBitMap(UDWORD PageIndex);
            ?????//取得位映射圖數(shù)值, 參數(shù)為分頁(yè)地址的頁(yè)號(hào)

            現(xiàn)在通過(guò)BitMap我們已經(jīng)可以了解到物理內(nèi)存分頁(yè)狀態(tài)下內(nèi)存的使用狀態(tài)了,但是仍然不能按頁(yè)分配和回收內(nèi)存。那么要如何設(shè)計(jì)分配和回收內(nèi)存頁(yè)呢?我們可以組織一個(gè)空閑頁(yè)鏈表,每分配一個(gè)頁(yè),就摘掉一個(gè)鏈表項(xiàng),每回收一個(gè)頁(yè),就往鏈表里加一個(gè)項(xiàng)。但是這樣有幾個(gè)缺點(diǎn),一來(lái)鏈表不穩(wěn)定,一旦出錯(cuò)就會(huì)造成內(nèi)存丟失或者重復(fù)分配進(jìn)而造成進(jìn)程間沖突,二來(lái)效率相對(duì)差些。最后我想到在UNIX中,磁盤(pán)塊的分配采用的是成組鏈接法,因?yàn)閮?nèi)存空閑頁(yè)在本質(zhì)上也是一種塊,因此我們可以把這個(gè)算法適當(dāng)?shù)母脑煲幌拢脕?lái)分配和回收空閑頁(yè)。我們知道,成組鏈接分配算法采用一個(gè)堆棧來(lái)進(jìn)行分配和回收操作。我們將空閑物理頁(yè)號(hào)按1024個(gè)為一組進(jìn)行遍組,這樣最多會(huì)有8組(因?yàn)閂enus最大支持32MB內(nèi)存),并設(shè)計(jì)一個(gè)指針,在初始化時(shí)讓它指向第一組的開(kāi)頭,當(dāng)分配出去一個(gè)空閑頁(yè)面時(shí),令指針指向組中的下一個(gè)空閑物理塊號(hào),而當(dāng)回收一個(gè)空閑物理頁(yè)時(shí),則將其頁(yè)號(hào)記入上一個(gè)分配出去的頁(yè)號(hào)的位置。簡(jiǎn)單說(shuō),就是當(dāng)分配空閑物理頁(yè)時(shí)做出棧操作,當(dāng)回收時(shí)做壓棧操作。而在每組的末尾,記錄著新一組的起始物理地址,當(dāng)操作指針指向當(dāng)前組的末尾時(shí),就會(huì)跳到新一組的開(kāi)始繼續(xù)進(jìn)行分配。由于內(nèi)存的分配和回收要求高效率的操作,再加上這是Venus使用的數(shù)據(jù),因此對(duì)8個(gè)組的地址做如下規(guī)定:每組和每組之間保持連續(xù),也就是說(shuō)這8個(gè)組必須存放在連續(xù)的物理內(nèi)存空間里。每組之間以4個(gè)字節(jié)相隔。這4個(gè)字節(jié)中記錄的是下一組的起始物理地址。為了能明確知道當(dāng)前分配指針是否已經(jīng)指向了當(dāng)前組的末尾,在Venus中需要再增加一些數(shù)據(jù)成員來(lái)記錄分配的次數(shù)。由于Venus最大支持到32MB ,因此采用一個(gè)字的長(zhǎng)度來(lái)記錄空閑物理頁(yè)號(hào)。由此得到8組占用的長(zhǎng)度:1024×2Byte×8組=16KB=4頁(yè)。同樣做為Venus的數(shù)據(jù),我將起存儲(chǔ)位置設(shè)置為內(nèi)存低地址區(qū),緊挨BitMap之后,即:0x0000400- 0x000441F。新增加的數(shù)據(jù)成員如下:

            ??UDWORD??StackEsp;?//MallocStack操作指針.
            ??UDWORD??MallocCounter;?//分配次數(shù)計(jì)數(shù)器 用來(lái)記錄是否需要取下個(gè)可用頁(yè)面組或生成新可用頁(yè)面組??
            ??UDWORD??GroupIndex;???? //當(dāng)前操作的組號(hào)

            對(duì)應(yīng)分配和回收操作,分別有2個(gè)函數(shù)提供支持,具體實(shí)現(xiàn)代碼在最后給出:
            ??
            UDWORD?APIENTRY?Fn_Service_MallocOnePage();??
            ?????//分配一個(gè)頁(yè)面

            ??UDWORD?APIENTRY?Fn_Service_FreeOnePage(UDWORD PageIndex);?
            ?????//回收一個(gè)頁(yè)面,參數(shù)為待回收的頁(yè)面地址號(hào)

            到目前,Venus具有了虛擬地址變換,按頁(yè)為單位對(duì)內(nèi)存進(jìn)行分配/回收操作,記錄/查詢內(nèi)存使用狀態(tài)的功能。
            接著,我們來(lái)實(shí)現(xiàn)第二個(gè)功能部分:利用指定的頁(yè)表進(jìn)行地址變換,得到物理地址。那么如何利用頁(yè)表呢,這就要牽扯到頁(yè)表的數(shù)據(jù)結(jié)構(gòu)了。那么我們先來(lái)設(shè)計(jì)好頁(yè)表。在分頁(yè)系統(tǒng)中,頁(yè)表的基本功能是將邏輯頁(yè)地址映射為物理頁(yè)地址。實(shí)現(xiàn)時(shí),通常采用這樣的設(shè)計(jì):在邏輯頁(yè)表中的每一個(gè)頁(yè)表項(xiàng)中存放的是物理頁(yè)號(hào)的地址。這樣通過(guò)讀取頁(yè)表項(xiàng),可以得到對(duì)應(yīng)邏輯頁(yè)在物理內(nèi)存中的物理頁(yè)號(hào),再和頁(yè)內(nèi)偏移量相拼,就得到了要訪問(wèn)的物理地址。如上文所寫(xiě)到的,在分頁(yè)系統(tǒng)中,進(jìn)程訪問(wèn)內(nèi)存使用的都是虛擬地址,也就是說(shuō),進(jìn)程總是認(rèn)為自己的存儲(chǔ)地址是從0x0開(kāi)始的。進(jìn)程進(jìn)行內(nèi)存訪問(wèn)時(shí),傳遞給Venus的是一個(gè)虛擬的地址,Venus將這個(gè)虛擬的地址做分頁(yè)變換,取得對(duì)應(yīng)這個(gè)虛擬地址的分頁(yè)地址,分頁(yè)地址中包含了頁(yè)號(hào)和頁(yè)內(nèi)偏移量,然后Venus再利用得到的頁(yè)號(hào),去這個(gè)進(jìn)程的頁(yè)表中對(duì)應(yīng)的頁(yè)表項(xiàng)里取得物理頁(yè)號(hào)的地址,最后將取得的頁(yè)號(hào)地址再和頁(yè)內(nèi)偏移量相拼,就得到了物理地址。這樣就完成了一次由虛擬地址到物理地址的映射。回到剛才的設(shè)計(jì)上,頁(yè)表項(xiàng)必須有至少以下2個(gè)數(shù)據(jù)成員來(lái)完成地址的映射:
            ?UDWORD?PageIndex;?? //頁(yè)索引號(hào)用于共系統(tǒng)查找(目前未用)
            ?UDWORD?PageBlock;?? //物理頁(yè)號(hào) 保存該頁(yè)表項(xiàng)映射的真實(shí)物理頁(yè)號(hào)地址
            而實(shí)際上,為了支持虛擬存儲(chǔ)技術(shù)和共享保護(hù)等諸多功能,頁(yè)表項(xiàng)還需要其他的數(shù)據(jù)結(jié)構(gòu)支持,比如,為了供換頁(yè)進(jìn)程參看,頁(yè)表項(xiàng)需要提供當(dāng)前單位時(shí)間內(nèi)自身是否被訪問(wèn),是否被修改,當(dāng)前該頁(yè)是否在內(nèi)存,單位時(shí)間內(nèi)頁(yè)面被訪問(wèn)的次數(shù) 等等的信息,因此綜合了一下,我將頁(yè)表項(xiàng)設(shè)計(jì)如下:
            ??UDWORD?PageIndex;?? //頁(yè)索引號(hào)用于共系統(tǒng)查找(目前未用)
            ??UDWORD?PageBlock;?? //物理頁(yè)號(hào) 保存該頁(yè)表項(xiàng)映射的真實(shí)物理頁(yè)地址
            ??UDWORD?AccessCounter; //訪問(wèn)計(jì)數(shù)器,用來(lái)記錄該頁(yè)面被訪問(wèn)的次數(shù)
            ??UDWORD?PageStatus;?? //頁(yè)面狀態(tài)標(biāo)志,標(biāo)志頁(yè)面是在內(nèi)存中還是在外存中,共換頁(yè)進(jìn)程參考
            ??BOOL?IsModify;?//頁(yè)面是否被修改 共換頁(yè)進(jìn)程參考
            ??BOOL?IsAccess;?//頁(yè)是否被訪問(wèn),共換頁(yè)進(jìn)程參考
            ??UDWORD?SwapAddress;??? //外存地址.頁(yè)面被存放于外存的地址
            這些數(shù)據(jù)結(jié)構(gòu)將為以后設(shè)計(jì)換頁(yè)進(jìn)程提供有力的支持。Venus作為底層內(nèi)核,必須能向高層部分提供對(duì)頁(yè)表項(xiàng)內(nèi)容的查詢和修改操作,以及當(dāng)新生成一個(gè)頁(yè)表項(xiàng)時(shí),應(yīng)該能按高層的要求,進(jìn)行頁(yè)表項(xiàng)初始化操作,初始化主要用來(lái)給新頁(yè)表項(xiàng)分配一個(gè)空閑物理頁(yè)面供其映射。
            ?在頁(yè)表項(xiàng)的數(shù)據(jù)成員中,PageBlock和PageIndex只能在初始化時(shí)由初始化函數(shù)修改,一旦初始化成功完成,以后除非回收頁(yè)面,否則不能再修改。而其他數(shù)據(jù)成員,則可以由高層按需要進(jìn)行修改。基于以上設(shè)定,頁(yè)表項(xiàng)應(yīng)該具有的操作集有:

            UDWORD?APIENTRY??Fn_Service_Init(UDWORD?Init_PageIndex); //頁(yè)表項(xiàng)對(duì)象初始化函數(shù),參數(shù)為頁(yè)索引號(hào).
            //該函數(shù)將請(qǐng)求內(nèi)核分配一個(gè)空閑物理頁(yè)面以用來(lái)初始化,并將該頁(yè)面地址記入PageBlock中
            ??
            UDWORD?APIENTRY??Fn_Service_Free();//該函數(shù)將請(qǐng)求內(nèi)核釋放其所映射的物理頁(yè)面,并將PageBlock的數(shù)值設(shè)置為NO_ALLOCATION
            //被釋放的頁(yè)面將被放入內(nèi)核管理的分配堆棧,共其他進(jìn)程使用

            UDWORD?APIENTRY??Fn_Service_GetPageBlock();? //取得PageBlock的值
            UDWORD?APIENTRY??Fn_Service_GetPageStatu(); //取得PageStatu的值
            UDWORD?APIENTRY??Fn_Service_GetAccessCounter();//取得AccessCounter的值
            UDWORD?APIENTRY??Fn_Service_GetIsModify(); //取得IsModify的值
            UDWORD?APIENTRY??Fn_Service_GetIsAccess(); //取得IsAccess的值


            VOID?APIENTRY??Fn_Service_SetPageStatu(UDWORD?NewStatu); //設(shè)置PageStatu的值

            VOID?APIENTRY??Fn_Service_IncAccessCounter(); //AccessCounter自增1
            VOID?APIENTRY??Fn_Service_SetIsModidy(BOOL?NewFlag); //設(shè)置IsModify的值
            VOID?APIENTRY??Fn_Service_SetIsAccess(BOOL?NewFlag);? //設(shè)置IsAccess的值

            VOID?APIENTRY??Fn_Service_SetSwapAddress(UDWORD?NewSwapAddress);
            //設(shè)置SwapAddress的值

            當(dāng)頁(yè)表項(xiàng)設(shè)計(jì)好后,就可以實(shí)現(xiàn)Venus的第二部分功能,利用頁(yè)表進(jìn)行地址變換,映射出要訪問(wèn)的真實(shí)物理地址。對(duì)內(nèi)存的訪問(wèn),無(wú)非是讀或者寫(xiě),因此Venus需要提供一個(gè)內(nèi)存訪問(wèn)接口。EmuHAL中提供了對(duì)物理內(nèi)存進(jìn)行按字節(jié),字,雙字讀取/寫(xiě)入的接口,因此Venus中也將提供按字節(jié),字,雙字讀取/寫(xiě)入的接口。到這里有一個(gè)問(wèn)題,就是什么時(shí)候進(jìn)行利用頁(yè)表和分頁(yè)地址進(jìn)行物理地址的映射。可以有2個(gè)方案,第一,加載虛擬地址后立刻進(jìn)行分頁(yè)地址到物理地址的映射,這時(shí)候當(dāng)然需要頁(yè)表的支持。第二,加載虛擬地址后并不立刻進(jìn)行分頁(yè)地址到物理的映射,而是等到需要執(zhí)行讀/寫(xiě)操作時(shí),才利用指定的頁(yè)表進(jìn)行地址映射,隨后進(jìn)行訪問(wèn)操作。我在這里選擇了第二個(gè)方案。因?yàn)槲矣X(jué)得加載虛擬地址后并不一定馬上要進(jìn)行內(nèi)存操作,但是向Venus請(qǐng)求了讀寫(xiě)操作后則必須立刻執(zhí)行讀/寫(xiě),因此我在這里提供給高層2個(gè)地址方面的接口,一個(gè)只先加載地址并進(jìn)行虛擬地址到分頁(yè)地址的變換,另一個(gè)接口就是由上文的6個(gè)讀寫(xiě)函數(shù)中的參數(shù)提供的,使用這6個(gè)函數(shù)時(shí),Venus會(huì)一次性完成加載虛擬地址變換為分頁(yè)地址和利用分頁(yè)地址及頁(yè)表完成分頁(yè)地址到物理地址的轉(zhuǎn)換,并將讀寫(xiě)操作傳遞給EmuHAL層去執(zhí)行。Venus提供的讀寫(xiě)函數(shù)接口如下:
            BYTE?APIENTRY?Fn_Service_ReadByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress);
            ?????//按字節(jié)方式(8bit)讀取

            VOID?APIENTRY?Fn_Service_WriteByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按字節(jié)方式(8bit)寫(xiě)入
            ??
            WORD?APIENTRY?Fn_Service_ReadWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress);
            ?????//按字方式(16bit)讀取
            ??
            VOID?APIENTRY?Fn_Service_WriteWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按字方式(16bit)寫(xiě)入

            DWORD?APIENTRY?Fn_Service_ReadDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress);
            ?????//按雙字方式(32bit)讀取
            ??
            VOID?APIENTRY?Fn_Service_WriteDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ???????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按雙字方式(32bit)寫(xiě)入
            ?
            到這里,第二和第三部分功能就相繼實(shí)現(xiàn)了,作為底層來(lái)說(shuō),現(xiàn)在基本的功能已經(jīng)實(shí)現(xiàn)了,但是還有很多的不足,比如,內(nèi)核的健壯性問(wèn)題。上面的各個(gè)功能設(shè)計(jì)都沒(méi)有考慮到操作數(shù)據(jù)錯(cuò)誤帶來(lái)的影響,并且對(duì)Venus使用的內(nèi)存部分完全沒(méi)有進(jìn)行保護(hù),任何進(jìn)程都可以輕松訪問(wèn)到系統(tǒng)使用的內(nèi)存,這是相當(dāng)危險(xiǎn)的。
            上面說(shuō)了這么多,我把具體實(shí)現(xiàn)的代碼貼在下面,這些代碼實(shí)現(xiàn)上面說(shuō)的Venus 的各個(gè)基本功能,并且最了相對(duì)比較好的安全性檢測(cè),并且基本保證了在EmuHAL下系統(tǒng)用內(nèi)存空間不可訪問(wèn)。
            Memoary_Class_Define.h
            //================================================================//
            #ifndef _MEMOARY_CLASS_DEFINE_H
            #define _MEMOARY_CLASS_DEFINE_H

            #include "../Include/Memoary_Define.h"
            #include "../Include/Memoary_Class_Lv1Pt_Define.h"
            class?CMemoaryKernel? //內(nèi)存分頁(yè)管理內(nèi)核接口類
            {
            ?public:
            ??virtual?VOID??APIENTRY?Fn_Service_Init(UDWORD?NewMemoarySize)=0;
            ??//內(nèi)核啟動(dòng),初始化函數(shù),必須在EmuHAL被初始化后調(diào)用,否則會(huì)因?yàn)闆](méi)有EmuHAL層支持而出錯(cuò).
            ??//同時(shí)不調(diào)用本函數(shù)則內(nèi)核本身也不會(huì)初始化,進(jìn)而導(dǎo)致Halt.

            ?public: //存儲(chǔ)器管理內(nèi)核狀態(tài)查詢操作服務(wù)集
            ??virtual UDWORD?APIENTRY?Fn_Service_GetErrorCode()=0; //取得內(nèi)核操作錯(cuò)誤狀態(tài)代碼
            ??virtual VOID?APIENTRY?Fn_Service_GetMemoaryStatu()=0;//當(dāng)前內(nèi)存使用情況查看接口
            ?
            ?public: //單位頁(yè)面分配/回收服務(wù)集
            ??virtual UDWORD?APIENTRY?Fn_Service_MallocOnePage()=0;??
            ?????//分配一個(gè)頁(yè)面,返回值為分配的頁(yè)面地址

            ??virtual UDWORD?APIENTRY?Fn_Service_FreeOnePage(UDWORD PageIndex)=0;?
            ?????//回收一個(gè)頁(yè)面,參數(shù)為待回收的頁(yè)號(hào)地址.注意,該函數(shù)不會(huì)回收任何由系統(tǒng)常駐的頁(yè)面或者非法頁(yè)面
            ??
            ?public: //讀寫(xiě)服務(wù)集? 第一個(gè)參數(shù)為L(zhǎng)v1頁(yè)表對(duì)象指針? 第二個(gè)參數(shù)為虛擬地址 第3個(gè)參數(shù)為待寫(xiě)入的數(shù)據(jù)
            ??virtual BYTE?APIENTRY?Fn_Service_ReadByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress)=0;
            ?????//按字節(jié)方式(8bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按字節(jié)方式(8bit)寫(xiě)入
            ??


            ??
            ??virtual WORD?APIENTRY?Fn_Service_ReadWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress)=0;
            ?????//按字方式(16bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按字方式(16bit)寫(xiě)入
            ??


            ??
            ??virtual DWORD?APIENTRY?Fn_Service_ReadDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress)=0;
            ?????//按雙字方式(32bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ???????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按雙字方式(32bit)寫(xiě)入
            ??
            };
            class?MemoaryKernel:public CMemoaryKernel
            {
            ?private:
            ??BOOL??IsPage;???? //是否分頁(yè)管理 正常初始化時(shí)為1,即使用分頁(yè)管理
            ??UDWORD??_SaveLinerAddress; //Map位圖存放的線性地址
            ??UDWORD??PageAddressIndex;? //分頁(yè)地址中的頁(yè)號(hào)地址?
            ??UDWORD??InPageOffset;??? //分頁(yè)地址中的頁(yè)內(nèi)偏移地址
            ??UDWORD??NowLineAddress;??? //當(dāng)前等待變換或者使用的虛擬地址
            ??UDWORD??StackEsp;?//MallocStack操作指針.
            ??UDWORD??MallocCounter;?//分配次數(shù)計(jì)數(shù)器 用來(lái)記錄是否需要取下個(gè)可用頁(yè)面組或生成新可用頁(yè)面組??
            ??UDWORD??ErrorCode;????? //錯(cuò)誤代碼變量
            ??UDWORD??GroupIndex;???? //當(dāng)前操作的組號(hào)
            ??UDWORD??MemoarySize;??? //當(dāng)前總共內(nèi)存容量
            ??UDWORD??MaxPageIndex;?//最大頁(yè)面號(hào),有初始化時(shí)的總計(jì)內(nèi)存容量決定.
            ?public:
            ??MemoaryKernel();
            ??~MemoaryKernel();
            ?
            ?private://內(nèi)部服務(wù)
            ??VOID?APIENTRY?Fn_TranslateLineAddress();? //虛擬地址分頁(yè)變換機(jī)構(gòu)
            ??VOID?APIENTRY?Fn_Service_Init_MallocStack(); //Malloc堆棧初始化函數(shù)
            ??VOID?APIENTRY?Fn_Service_LoadVirtualAddress(UDWORD VirtualAddress);
            ?????//加載待讀取或者寫(xiě)入的內(nèi)存地址.如果使用分頁(yè)模式,則內(nèi)核會(huì)將線性地址做拆分,
            ?????//在PageAddressIndex中放入頁(yè)號(hào)地址,在InPageOffset中放入頁(yè)內(nèi)偏移量地址??
            ??
            ?public: //內(nèi)存使用狀況查詢/設(shè)置/內(nèi)核初始化服務(wù)集
            ??virtual?VOID??APIENTRY?Fn_Service_Init(UDWORD?NewMemoarySize);
            ?????//內(nèi)核初始化函數(shù),負(fù)責(zé)啟動(dòng)內(nèi)核,設(shè)置位映射圖和Malloc堆棧??

            ??DWORD?APIENTRY?Fn_Service_SetBitMap(UDWORD PageIndex,BOOL Flag);
            ?????//設(shè)置位映射圖, 參數(shù)為分頁(yè)地址的頁(yè)號(hào)地址.

            ??DWORD?APIENTRY?Fn_Service_GetBitMap(UDWORD PageIndex);
            ?????//取得位映射圖數(shù)值, 參數(shù)為分頁(yè)地址的頁(yè)號(hào)地址.

            ?public: //單位頁(yè)面分配/回收服務(wù)集
            ??virtual?UDWORD?APIENTRY?Fn_Service_MallocOnePage();??
            ?????//分配一個(gè)頁(yè)面

            ??virtual UDWORD?APIENTRY?Fn_Service_FreeOnePage(UDWORD PageIndex);?
            ?????//回收一個(gè)頁(yè)面

            ?public: //存儲(chǔ)器管理內(nèi)核狀態(tài)查詢操作服務(wù)集
            ??virtual UDWORD?APIENTRY?Fn_Service_GetErrorCode(); //取得內(nèi)核操作錯(cuò)誤狀態(tài)代碼
            ??virtual VOID?APIENTRY?Fn_Service_GetMemoaryStatu();//當(dāng)前內(nèi)存使用情況查看接口
            ??
            ?public: //讀寫(xiě)服務(wù)集? 第一個(gè)參數(shù)為L(zhǎng)v1頁(yè)表對(duì)象指針? 第二個(gè)參數(shù)為虛擬地址 第3個(gè)參數(shù)為待寫(xiě)入的數(shù)據(jù)
            ??virtual BYTE?APIENTRY?Fn_Service_ReadByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress);
            ?????//按字節(jié)方式(8bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按字節(jié)方式(8bit)寫(xiě)入
            ??


            ??
            ??virtual WORD?APIENTRY?Fn_Service_ReadWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress);
            ?????//按字方式(16bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按字方式(16bit)寫(xiě)入
            ??


            ??
            ??virtual DWORD?APIENTRY?Fn_Service_ReadDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress);
            ?????//按雙字方式(32bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ???????????? UDWORD NewVirtualAddress,DWORD Value);
            ?????//按雙字方式(32bit)寫(xiě)入
            ??
            };

            #endif? //#ifndef _MEMOARY_CLASS_DEFINE_H

            //================================================================//
            Memoary_Class_Lv1PT_Define.h
            //================================================================//
            #ifndef?_MEMOARY_CLASS_LV1PT_DEFINE
            #define _MEMOARY_CLASS_LV1PT_DEFINE
            #include "../Include/Memoary_Define.h"

            class?Lv1_MemoaryTable
            {
            ?private:
            ??UDWORD?PageIndex;?? //頁(yè)索引號(hào)用于共系統(tǒng)查找(目前未用)
            ??UDWORD?PageBlock;?? //物理頁(yè)號(hào) 保存該頁(yè)表項(xiàng)映射的真實(shí)物理頁(yè)地址
            ??UDWORD?AccessCounter; //訪問(wèn)計(jì)數(shù)器,用來(lái)記錄該頁(yè)面被訪問(wèn)的次數(shù)
            ??UDWORD?PageStatus;?? //頁(yè)面狀態(tài)標(biāo)志,標(biāo)志頁(yè)面是在內(nèi)存中還是在外存中,共換頁(yè)進(jìn)程參考
            ??BOOL?IsModify;?//頁(yè)面是否被修改 共換頁(yè)進(jìn)程參考
            ??BOOL?IsAccess;?//頁(yè)是否被訪問(wèn),共換頁(yè)進(jìn)程參考
            ??UDWORD?SwapAddress;??? //外存地址.頁(yè)面被存放于外存的地址
            ?public:
            ??Lv1_MemoaryTable();
            ??~Lv1_MemoaryTable();
            ?
            ?public: //頁(yè)表項(xiàng)初始化服務(wù)集
            ??UDWORD?APIENTRY??Fn_Service_Init(UDWORD?Init_PageIndex); //頁(yè)表項(xiàng)對(duì)象初始化函數(shù),參數(shù)為頁(yè)索引號(hào).
            ???????//該函數(shù)將請(qǐng)求內(nèi)核分配一個(gè)空閑物理頁(yè)面以用來(lái)初始化,并將該頁(yè)面地址記入PageBlock中
            ??
            ??UDWORD?APIENTRY??Fn_Service_Free();//該函數(shù)將請(qǐng)求內(nèi)核釋放其所映射的物理頁(yè)面,并將PageBlock的數(shù)值設(shè)置為NO_ALLOCATION
            ????????? //被釋放的頁(yè)面將被放入內(nèi)核管理的分配堆棧,共其他進(jìn)程使用
            ?
            ?public: //頁(yè)表項(xiàng)狀態(tài)讀/寫(xiě)服務(wù)集
            ??//讀
            ??UDWORD?APIENTRY??Fn_Service_GetPageBlock();? //取得PageBlock的值
            ??UDWORD?APIENTRY??Fn_Service_GetPageStatu(); //取得PageStatu的值
            ??UDWORD?APIENTRY??Fn_Service_GetAccessCounter();//取得AccessCounter的值
            ??UDWORD?APIENTRY??Fn_Service_GetIsModify(); //取得IsModify的值
            ??UDWORD?APIENTRY??Fn_Service_GetIsAccess(); //取得IsAccess的值
            ??
            ??//寫(xiě)
            ??VOID?APIENTRY??Fn_Service_SetPageStatu(UDWORD?NewStatu); //設(shè)置PageStatu的值
            ??VOID?APIENTRY??Fn_Service_IncAccessCounter(); //AccessCounter自增1
            ??VOID?APIENTRY??Fn_Service_SetIsModidy(BOOL?NewFlag); //設(shè)置IsModify的值
            ??VOID?APIENTRY??Fn_Service_SetIsAccess(BOOL?NewFlag);? //設(shè)置IsAccess的值
            ??VOID?APIENTRY??Fn_Service_SetSwapAddress(UDWORD?NewSwapAddress); //設(shè)置SwapAddress的值
            };

            #endif //#ifndef?_MEMOARY_CLASS_LV1PT_DEFINE
            //====================================================================//
            Memoary_Define.h
            //====================================================================//
            #ifndef _MEMOARY_DEFINE_H
            #define _MEMOARY_DEFINE_H

            #define??MAX_MEMOARY???0x02000000?? //支持管理的最大內(nèi)存 32MB
            #define??MIN_RUN_MEMOARY???0x00006000?? //內(nèi)核運(yùn)行需要的最小內(nèi)存,以Byte計(jì)算
            #define??MAX_PAGE_NUMBER???0x00001FFF?//32MB內(nèi)存按4KB分頁(yè)的最大頁(yè)號(hào) 0-8191 共8192個(gè)
            #define??PAGE_SIZE???4096?//頁(yè)尺寸4KB為4096Byte
            #define??MAX_MEMOARY_STACK??1024??? //負(fù)責(zé)內(nèi)存分配回收的堆棧的長(zhǎng)度
            #define??NO_ALLOCATION???0x0FFFF


            #define??_I386??//類型關(guān)鍵字定義 定義為Intel 80386 及以后處理器專用
            #define??_STDAPI???????? //允許函數(shù)調(diào)用使用Win32 APIENTRY(__stdcall)方式
            #define??_IOSTREAM?//使用iostream.h作為I/O操作庫(kù)

            #include <Base.h>
            #include <EmuHAL.h>

            #pragma comment(lib,"EmuHAL.lib")


            #define??SWAPPER????0x00000000
            #define??MEMOARY????0x00000001
            #define??UNINIT????0x00000002


            //以下地址基于ExHal層中的內(nèi)存,可被視為物理內(nèi)存
            #define??SYSTEM_USE_START_LINE_ADDRESS???0x0000000
            #define??SYSTEM_USE_START_PAGE_ADDRESS???0x0000000

            #define??MEMOARY_MAP_BEGIN_STORE_LINE_ADDRESS??0x0000000
            #define??MEMOARY_MAP_END_STORE_LINE_ADDRESS??0x00003FF

            #define??MEMOARY_STACK_BEGIN_STORE_LINE_ADDRESS??0x0000400
            #define??MEMOARY_STACK_END_STORE_LINE_ADDRESS??0x000441F
            #define??MEMOARY_STACK_ESP????0x0004420

            #define??SYSTEM_USE_END_PAGE_ADDRESS???0x0000004
            #define??SYSTEM_USE_END_LINE_ADDRESS???0x0004423

            //錯(cuò)誤代碼定義:
            #define??NORMAL??????0x00000001
            #define??GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY?0xF0000000
            #define??GENERAL_PROTECT_ERROR_PAGE_INDEX_OVERFLOW?0xF0000001
            #define??MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY?0xF0000002
            #define??MEMOARY_FREE_ERROR_NO_MEMOARY_NEED_FREE??0xF0000003
            #define??MEMOARY_KERNEL_HALT_NO_ENOUGH_MEMOARY_FOR_INIT?0xF0000004
            #define??MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION?0xF0000005
            #define??MEMOARY_KERNEL_FREE_PAGE_FAILURE_PAGE_UNUSED?0xF0000006
            #define??MEMOARY_KERNEL_READ_ERROR_ADDRESS_OVERFLOW?0xF0000007
            #define??MEMOARY_KERNEL_WRITE_ERROR_ADDRESS_OVERFLOW?0xF0000008
            #define??MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY?0xF0000009
            #define??MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY?0xF000000A
            #define??MALLOC_STACK_END_FLAG????0xFFFFFFFF

            #define??LPCMEMOAEYKERNEL?CMemoaryKernel*

            //LPCMEMOAEYKERNEL?Fn_iKernel_GetMemoaryManager();??

            #endif? //#ifndef _MEMOARY_DEFINE_H

            //====================================================================//
            ?Memoary_Gloable_Define.h
            //====================================================================//
            #ifndef?_MEMOARY_GLOABLE_DEFINE_H
            #define?_MEMOARY_GLOABLE_DEFINE_H
            #include "./Include/Memoary_Define.h"
            #include "./Include/Memoary_Class_Define.h"
            #include "./Include/Memoary_Class_Lv1PT_Define.h"

            //接口對(duì)象
            MemoaryKernel?m_Venus;??? //存儲(chǔ)器管理核心對(duì)象
            LPCMEMOAEYKERNEL?APIENTRY?Fn_iKernel_GetMemoaryManager();
            #endif
            //===================================================================//
            MemoaryPageLib.h
            //===================================================================//
            #ifndef?_MEMPAGELIB_H
            #define?_MEMPAGELIB_H

            #define??MAX_MEMOARY???0x00800000?? //支持管理的最大內(nèi)存 32MB
            #define??MAX_PAGE_NUMBER???0x00001FFF?//32MB內(nèi)存按4KB分頁(yè)的最大頁(yè)號(hào) 0-8191 共8192個(gè)
            #define??PAGE_SIZE???4096?//頁(yè)尺寸4KB為4096Byte
            #define??MAX_MEMOARY_STACK??1024??? //負(fù)責(zé)內(nèi)存分配回收的堆棧的長(zhǎng)度


            #define??_I386??//類型關(guān)鍵字定義 定義為Intel 80386 及以后處理器專用
            #define??_STDAPI???????? //允許函數(shù)調(diào)用使用Win32 APIENTRY(__stdcall)方式
            #define??_IOSTREAM?//使用iostream.h作為I/O操作庫(kù)

            #include <Base.h>
            #include <EmuHAL.h>

            #pragma comment(lib,"EmuHAL.lib")

            #define??SWAPPER????0x00000000
            #define??MEMOARY????0x00000001
            #define??UNINIT????0x00000002


            //以下地址基于ExHal層中的內(nèi)存,可被視為物理內(nèi)存
            #define??SYSTEM_USE_START_LINE_ADDRESS???0x0000000
            #define??SYSTEM_USE_START_PAGE_ADDRESS???0x0000000

            #define??MEMOARY_MAP_BEGIN_STORE_LINE_ADDRESS??0x0000000
            #define??MEMOARY_MAP_END_STORE_LINE_ADDRESS??0x00003FF

            #define??MEMOARY_STACK_BEGIN_STORE_LINE_ADDRESS??0x0000400
            #define??MEMOARY_STACK_END_STORE_LINE_ADDRESS??0x000441F
            #define??MEMOARY_STACK_ESP????0x0004420

            #define??SYSTEM_USE_END_PAGE_ADDRESS???0x0000004
            #define??SYSTEM_USE_END_LINE_ADDRESS???0x0004423

            //頁(yè)表映射的空閑物理頁(yè)面的狀態(tài)標(biāo)志
            #define??SWAPPER????0x00000000?? //位于交換設(shè)備上
            #define??MEMOARY????0x00000001? //在內(nèi)存中
            #define??UNINIT????0x00000002? //尚未初始化的新頁(yè)表項(xiàng)


            //錯(cuò)誤代碼定義:
            #define??NORMAL??????0x00000001
            #define??GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY?0xF0000000
            #define??GENERAL_PROTECT_ERROR_PAGE_INDEX_OVERFLOW?0xF0000001
            #define??MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY?0xF0000002
            #define??MEMOARY_FREE_ERROR_NO_MEMOARY_NEED_FREE??0xF0000003
            #define??MEMOARY_KERNEL_HALT_NO_ENOUGH_MEMOARY_FOR_INIT?0xF0000004
            #define??MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION?0xF0000005
            #define??MEMOARY_KERNEL_FREE_PAGE_FAILURE_PAGE_UNUSED?0xF0000006
            #define??MEMOARY_KERNEL_READ_ERROR_ADDRESS_OVERFLOW?0xF0000007
            #define??MEMOARY_KERNEL_WRITE_ERROR_ADDRESS_OVERFLOW?0xF0000008
            #define??MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY?0xF0000009
            #define??MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY?0xF000000A
            #define??MALLOC_STACK_END_FLAG????0xFFFFFFFF


            class?Lv1_MemoaryTable
            {
            ?private:
            ??UDWORD?PageIndex;?? //頁(yè)索引號(hào)用于共系統(tǒng)查找(目前未用)
            ??UDWORD?PageBlock;?? //物理頁(yè)號(hào) 保存該頁(yè)表項(xiàng)映射的真實(shí)物理頁(yè)地址
            ??UDWORD?AccessCounter; //訪問(wèn)計(jì)數(shù)器,用來(lái)記錄該頁(yè)面被訪問(wèn)的次數(shù)
            ??UDWORD?PageStatus;?? //頁(yè)面狀態(tài)標(biāo)志,標(biāo)志頁(yè)面是在內(nèi)存中還是在外存中,共換頁(yè)進(jìn)程參考
            ??BOOL?IsModify;?//頁(yè)面是否被修改 共換頁(yè)進(jìn)程參考
            ??BOOL?IsAccess;?//頁(yè)是否被訪問(wèn),共換頁(yè)進(jìn)程參考
            ??UDWORD?SwapAddress;??? //外存地址.頁(yè)面被存放于外存的地址
            ?public:
            ??Lv1_MemoaryTable();
            ??~Lv1_MemoaryTable();
            ?
            ?public: //頁(yè)表項(xiàng)初始化服務(wù)集
            ??UDWORD?APIENTRY??Fn_Service_Init(UDWORD?Init_PageIndex); //頁(yè)表項(xiàng)對(duì)象初始化函數(shù),參數(shù)為頁(yè)索引號(hào).
            ???????//該函數(shù)將請(qǐng)求內(nèi)核分配一個(gè)空閑物理頁(yè)面以用來(lái)初始化,并將該頁(yè)面地址記入PageBlock中
            ??
            ??UDWORD?APIENTRY??Fn_Service_Free();//該函數(shù)將請(qǐng)求內(nèi)核釋放其所映射的物理頁(yè)面,并將PageBlock的數(shù)值設(shè)置為NO_ALLOCATION
            ????????? //被釋放的頁(yè)面將被放入內(nèi)核管理的分配堆棧,共其他進(jìn)程使用
            ?
            ?public: //頁(yè)表項(xiàng)狀態(tài)讀/寫(xiě)服務(wù)集
            ??//讀
            ??UDWORD?APIENTRY??Fn_Service_GetPageBlock();? //取得PageBlock的值
            ??UDWORD?APIENTRY??Fn_Service_GetPageStatu(); //取得PageStatu的值
            ??UDWORD?APIENTRY??Fn_Service_GetAccessCounter();//取得AccessCounter的值
            ??UDWORD?APIENTRY??Fn_Service_GetIsModify(); //取得IsModify的值
            ??UDWORD?APIENTRY??Fn_Service_GetIsAccess(); //取得IsAccess的值
            ??
            ??//寫(xiě)
            ??VOID?APIENTRY??Fn_Service_SetPageStatu(UDWORD?NewStatu); //設(shè)置PageStatu的值
            ??VOID?APIENTRY??Fn_Service_IncAccessCounter(); //AccessCounter自增1
            ??VOID?APIENTRY??Fn_Service_SetIsModidy(BOOL?NewFlag); //設(shè)置IsModify的值
            ??VOID?APIENTRY??Fn_Service_SetIsAccess(BOOL?NewFlag);? //設(shè)置IsAccess的值
            ??VOID?APIENTRY??Fn_Service_SetSwapAddress(UDWORD?NewSwapAddress); //設(shè)置SwapAddress的值
            };


            class?CMemoaryKernel
            {
            ?public:
            ??virtual?VOID??APIENTRY?Fn_Service_Init(UDWORD?NewMemoarySize)=0;
            ??//內(nèi)核啟動(dòng),初始化函數(shù),必須在EmuHAL被初始化后調(diào)用,否則會(huì)出錯(cuò)

            ?public: //存儲(chǔ)器管理內(nèi)核狀態(tài)查詢操作服務(wù)集
            ??virtual UDWORD?APIENTRY?Fn_Service_GetErrorCode()=0; //取得內(nèi)核操作錯(cuò)誤狀態(tài)代碼
            ??virtual VOID?APIENTRY?Fn_Service_GetMemoaryStatu()=0;//當(dāng)前內(nèi)存使用情況查看接口
            ?
            ?public: //單位頁(yè)面分配/回收服務(wù)集
            ??virtual UDWORD?APIENTRY?Fn_Service_MallocOnePage()=0;??
            ?????//分配一個(gè)頁(yè)面

            ??virtual UDWORD?APIENTRY?Fn_Service_FreeOnePage(UDWORD PageIndex)=0;?
            ?????//回收一個(gè)頁(yè)面
            ??
            ?public: //讀寫(xiě)服務(wù)集? 第一個(gè)參數(shù)為L(zhǎng)v1頁(yè)表對(duì)象指針? 第二個(gè)參數(shù)為虛擬地址 第3個(gè)參數(shù)為待寫(xiě)入的數(shù)據(jù)
            ??virtual BYTE?APIENTRY?Fn_Service_ReadByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress)=0;
            ?????//按字節(jié)方式(8bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按字節(jié)方式(8bit)寫(xiě)入
            ??


            ??
            ??virtual WORD?APIENTRY?Fn_Service_ReadWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ?????????? UDWORD NewVirtualAddress)=0;
            ?????//按字方式(16bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按字方式(16bit)寫(xiě)入
            ??


            ??
            ??virtual DWORD?APIENTRY?Fn_Service_ReadDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ??????????? UDWORD NewVirtualAddress)=0;
            ?????//按雙字方式(32bit)讀取
            ??
            ??virtual VOID?APIENTRY?Fn_Service_WriteDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ???????????? UDWORD NewVirtualAddress,DWORD Value)=0;
            ?????//按雙字方式(32bit)寫(xiě)入
            ??
            };

            #define??LPCMEMOAEYKERNEL?CMemoaryKernel*??

            LPCMEMOAEYKERNEL APIENTRY?Fn_iKernel_GetMemoaryManager();
            #endif
            //====================================================================//
            Class_Lv1pt.cpp
            //====================================================================//
            #ifndef?_CLASS_LV1_PT
            #define?_CLASS_LV1_PT
            #include "../Include/Memoary_Class_Lv1Pt_Define.h"
            #include "../Include/Memoary_Class_Define.h"

            extern??MemoaryKernel???m_Venus;

            Lv1_MemoaryTable::~Lv1_MemoaryTable()
            {;}

            Lv1_MemoaryTable::Lv1_MemoaryTable()
            {
            ?PageBlock? = NO_ALLOCATION;
            ?PageStatus = UNINIT;
            }


            //頁(yè)表項(xiàng)對(duì)象初始化函數(shù),參數(shù)為頁(yè)索引號(hào).
            //該函數(shù)將請(qǐng)求內(nèi)核分配一個(gè)空閑物理頁(yè)面以用來(lái)初始化,并將該頁(yè)面地址記入PageBlock中
            UDWORD APIENTRY?Lv1_MemoaryTable::Fn_Service_Init(UDWORD?Init_PageIndex)
            {
            ?PageIndex = Init_PageIndex;
            ?if ((PageBlock == NO_ALLOCATION) && (PageStatus == UNINIT))
            ??{
            ???PageBlock = m_Venus.Fn_Service_MallocOnePage();
            ???if (this->PageBlock != MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY)
            ????{
            ?????AccessCounter = 0;
            ?????IsAccess = FALSE;
            ?????IsModify = FALSE;
            ?????PageStatus = MEMOARY;
            ?????SwapAddress = 0x0;
            ?????return?SUCCESS;
            ????}
            ???else
            ????{
            ?????PageBlock = NO_ALLOCATION;
            ?????return?FAILURE;
            ????}
            ??}
            ?else
            ??{
            ???return?FAILURE;
            ??}
            }


            //該函數(shù)將請(qǐng)求內(nèi)核釋放其所映射的物理頁(yè)面,并將PageBlock的數(shù)值設(shè)置為NO_ALLOCATION
            //被釋放的頁(yè)面將被放入內(nèi)核管理的分配堆棧,共其他進(jìn)程使用
            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_Free()
            {
            ?UDWORD?Resault = MEMOARY_KERNEL_FREE_PAGE_FAILURE_PAGE_UNUSED;
            ?_asm
            ??{
            ???mov?EAX,this
            ???cmp?[EAX]this.PageStatus,UNINIT
            ???je?Exit
            ???cmp?[EAX]this.PageBlock,NO_ALLOCATION
            ???je?Exit
            ??}
            ?
            ?Resault = m_Venus.Fn_Service_FreeOnePage(PageBlock);
            ?_asm?
            ??{
            ???cmp?EAX,SUCCESS
            ???jne?Exit
            ??}
            ?PageBlock = NO_ALLOCATION;
            ?PageStatus = UNINIT;
            Exit:?
            ?return?Resault;
            }

            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_GetPageBlock()
            {
            ?return?PageBlock;
            }

            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_GetPageStatu()
            {
            ?return?PageStatus;
            }

            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_GetAccessCounter()
            {
            ?return?AccessCounter;
            }

            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_GetIsModify()
            {
            ?return?IsModify;
            }

            UDWORD?APIENTRY?Lv1_MemoaryTable::Fn_Service_GetIsAccess()
            {
            ?return?IsAccess;
            }

            VOID?APIENTRY?Lv1_MemoaryTable::Fn_Service_SetPageStatu(UDWORD?NewStatu)
            {
            ?PageStatus = NewStatu;
            }

            VOID?APIENTRY?Lv1_MemoaryTable::Fn_Service_IncAccessCounter()
            {
            ?AccessCounter++;
            }

            VOID?APIENTRY?Lv1_MemoaryTable::Fn_Service_SetIsModidy(BOOL?NewFlag)
            {
            ?IsModify = NewFlag;
            }
            VOID?APIENTRY?Lv1_MemoaryTable::Fn_Service_SetIsAccess(BOOL?NewFlag)
            {
            ?IsAccess = NewFlag;
            }

            VOID?APIENTRY?Lv1_MemoaryTable::Fn_Service_SetSwapAddress(UDWORD?NewSwapAddress)
            {
            ?SwapAddress = NewSwapAddress;
            }
            #endif

            //===================================================================//
            Main_Source.cpp
            //===================================================================//
            #include "./Include/Memoary_Gloable_Define.h"
            //接口函數(shù)
            LPCMEMOAEYKERNEL?APIENTRY?Fn_iKernel_GetMemoaryManager()
            {
            ?return?(LPCMEMOAEYKERNEL)(&m_Venus);
            }

            //====================================================================//
            MemoaryKernel.cpp
            //====================================================================//
            #include "../Include/Memoary_Class_Define.h"

            MemoaryKernel::MemoaryKernel()
            {;}


            MemoaryKernel::~MemoaryKernel()
            {;}

            //內(nèi)核初始化函數(shù) 參數(shù)為物理內(nèi)存容量
            VOID? APIENTRY?MemoaryKernel::Fn_Service_Init(UDWORD?NewMemoarySize)
            {
            ?_asm?//物理內(nèi)存容量是否夠內(nèi)核啟動(dòng)運(yùn)行
            ??{
            ???mov?EAX,[NewMemoarySize]
            ???cmp?EAX,MIN_RUN_MEMOARY
            ???jae?KernelStart
            ???mov?EAX,this
            ???mov?[EAX]this.ErrorCode,MEMOARY_KERNEL_HALT_NO_ENOUGH_MEMOARY_FOR_INIT
            ??}
            ?cout<<"No Enough Memoary for MemoaryKernel(Venus) Init itself."<<endl;
            ?cout<<"EmuSolaris SYSTEM HALTTED Now."<<endl;
            ?_asm?
            ??{
            ???pop???????? edi
            ???pop???????? esi
            ???mov???????? esp,ebp
            ???pop???????? ebp
            ???ret???????? 8
            ??}

            ?if(NewMemoarySize > MAX_MEMOARY) {NewMemoarySize = MAX_MEMOARY;}
            ?//如果物理內(nèi)存容量超過(guò)了能管理的最大容量,則按能支持的最大容量處理,更大的地址看不見(jiàn)……=.=

            KernelStart:
            ?
            ?MemoarySize = NewMemoarySize;
            ?UDWORD?SystemUsed = SYSTEM_USE_START_PAGE_ADDRESS;
            ?_SaveLinerAddress? = MEMOARY_MAP_BEGIN_STORE_LINE_ADDRESS;
            ?InPageOffset = NULL;
            ?PageAddressIndex = NULL;
            ?NowLineAddress = NULL;
            ?MallocCounter = 0;
            ?ErrorCode = NORMAL;
            ?GroupIndex = 1;

            ?_asm//這段匯編完成計(jì)算出NewMemoarySize對(duì)應(yīng)的最大頁(yè)號(hào)地址
            ??{
            ???push?EAX
            ???push?EDX
            ???push?ECX
            ???
            ???mov?EAX,[NewMemoarySize]
            ???mov?EDX,EAX
            ???and?EAX,0x0000FFFF
            ???
            ???
            ???shr?EDX,0x010
            ???and?EDX,0x0000FFFF
            ???
            ???mov?CX,0x01000
            ???div?CX

            ???sub?EAX,1

            ???and?EAX,0x0000FFFF

            ???mov?ECX,this
            ???mov?[ECX]this.MaxPageIndex,EAX

            ???
            ???pop?ECX
            ???pop?EDX
            ???pop?EAX
            ?
            ??}
            ?for(SystemUsed;SystemUsed<=SYSTEM_USE_END_PAGE_ADDRESS;SystemUsed++) //為系統(tǒng)使用的內(nèi)存做保留操作 :)
            ??{??????????????????? //這些地址將被用來(lái)保存 內(nèi)存分頁(yè)使用狀態(tài)映射圖和用于內(nèi)存分配的Malloc堆棧
            ???Fn_Service_SetBitMap(SystemUsed,USED);
            ??}

            ?StackEsp = MEMOARY_STACK_BEGIN_STORE_LINE_ADDRESS;//Malloc堆棧指針指向棧頂
            ?Fn_Service_Init_MallocStack(); //Malloc堆棧初始化
            ?IsPage = TRUE; //設(shè)置系統(tǒng)使用分頁(yè)模式管理內(nèi)存 至此內(nèi)核初始化完畢.
            }


            //內(nèi)存描述Map的設(shè)置函數(shù).
            DWORD APIENTRY?MemoaryKernel::Fn_Service_SetBitMap(UDWORD PageIndex,BOOL Flag)
            {?
            ?UDWORD?OffsetAddress;
            ?DWORD?Content;
            ?BYTE?Shift;

            ?if (PageIndex>MaxPageIndex) {return?FAILURE;}

            ?_asm
            ??{
            ?????? //保存寄存器
            ???push?ECX
            ???push?EDX
            ???push?EBX
            ???

            ???mov?EAX,[PageIndex]? //比較頁(yè)號(hào)是否合法,32MB內(nèi)存按4KB分頁(yè)支持的最大頁(yè)號(hào)為0-8192
            ???cmp?EAX,MAX_PAGE_NUMBER
            ???ja?EXIT

            ???mov?CL,0x020? //映射常數(shù)因子 由于x86寄存器是32bit長(zhǎng),所以取為32方便對(duì)齊運(yùn)算
            ???div?CL?? //取得頁(yè)號(hào)對(duì)應(yīng)的位映射在Map中的段偏移量,段長(zhǎng)以4Byte為單位。
            ???mov?BX,AX?? //取得頁(yè)號(hào)對(duì)應(yīng)的位映射在段內(nèi)的偏移量,并保存在BX中
            ???and?EAX,0x000000FF
            ???mov?CL,0x04?? //段長(zhǎng)常數(shù)因子,取4表示4Byte,因?yàn)?Byte = 32bit.
            ???mul?CL?? //取得自Map圖開(kāi)始到對(duì)應(yīng)段的具體地址,以Byte為單位.

            ???mov?[Shift],BH?//將段內(nèi)偏移量放Shift
            ???
            ???and?EAX,0x0000FFFF? //EAX高16位清空
            ???mov?[OffsetAddress],EAX //保存段偏移地址
            ???
            ??}
            ?//讀取Map中對(duì)應(yīng)的段
            ?Content = Fn_ReadDword(_SaveLinerAddress+OffsetAddress);
            ???
            ?_asm
            ??{
            ???mov?EAX,[Content]?//取得map圖中的對(duì)應(yīng)段入EAX
            ???xor?EDX,EDX
            ???mov?DL,[Flag]?
            ???cmp?DL,0???
            ???mov?EDX,0x01
            ???mov?CL,[Shift]
            ???je?SetUnuse
            ??//SetUse:?????//設(shè)置對(duì)應(yīng)位為1的操作
            ???shl?EDX,CL???//移動(dòng)shift位
            ???or?EAX,EDX???//設(shè)置對(duì)應(yīng)位
            ???mov?[Content],EAX?
            ???jmp?Exit
            ??SetUnuse:?????//設(shè)置對(duì)應(yīng)位為0的操作??
            ???shl?EDX,CL
            ???not?EDX
            ???and?EAX,EDX
            ???mov?[Content],EAX
            ??EXit:??????//恢復(fù)寄存器,退出。
            ???pop?EBX
            ???pop?EDX
            ???pop?ECX
            ???
            ??}
            ?Fn_WriteDword(_SaveLinerAddress+OffsetAddress,Content);//將對(duì)應(yīng)位寫(xiě)回Map

            ?return?SUCCESS;
            }


            //讀取內(nèi)存使用狀態(tài)Map圖的函數(shù)
            DWORD?APIENTRY?MemoaryKernel::Fn_Service_GetBitMap(UDWORD PageIndex)
            {
            ?UDWORD?OffsetAddress;
            ?DWORD?Content=GENERAL_PROTECT_ERROR_PAGE_INDEX_OVERFLOW;? //如果出錯(cuò),
            ????????//則這里放的就是出錯(cuò)代碼
            ?BYTE?Shift;

            ?if (PageIndex > MaxPageIndex) {return?FAILURE;}

            ?_asm
            ??{
            ??????? //保存寄存器
            ???push?ECX
            ???push?EDX
            ???push?EBX
            ???

            ???mov?EAX,[PageIndex]? //比較頁(yè)號(hào)是否合法,32MB內(nèi)存按4KB分頁(yè)支持的最大頁(yè)號(hào)為0-8192
            ???cmp?EAX,MAX_PAGE_NUMBER
            ???ja?EXIT

            ???mov?CL,0x020? //映射常數(shù)因子 由于x86寄存器是32bit長(zhǎng),所以取為32方便對(duì)齊運(yùn)算
            ???div?CL?? //取得頁(yè)號(hào)對(duì)應(yīng)的位映射在Map中的段偏移量,段長(zhǎng)以4Byte為單位。
            ???mov?BX,AX?? //取得頁(yè)號(hào)對(duì)應(yīng)的位映射在段內(nèi)的偏移量,并保存在BX中
            ???and?EAX,0x000000FF
            ???mov?CL,0x04?? //段長(zhǎng)常數(shù)因子,取4表示4Byte,因?yàn)?Byte = 32bit.
            ???mul?CL?? //取得自Map圖開(kāi)始到對(duì)應(yīng)段的具體地址,以Byte為單位.

            ???mov?[Shift],BH?//將段內(nèi)偏移量放Shift
            ???
            ???and?EAX,0x0000FFFF? //EAX高16位清空
            ???mov?[OffsetAddress],EAX? //將總線性偏移量放對(duì)應(yīng)變量
            ???
            ??}
            ?
            ?Content = Fn_ReadDword(_SaveLinerAddress+OffsetAddress);
            ???
            ?_asm
            ??{
            ???mov?EAX,[Content]?//取得map圖中的對(duì)應(yīng)段入EAX
            ???mov?CL,[Shift]
            ???shr?EAX,CL??//將EAX中對(duì)應(yīng)的位移動(dòng)到最低位
            ???and?EAX,0x00000001? //其他位清0
            ???mov?[Content],EAX? //保存在Content中
            ??EXit:??????//恢復(fù)寄存器,退出。
            ???pop?EBX
            ???pop?EDX
            ???pop?ECX
            ???
            ??}
            ?

            ?return?Content;
            }

            //加載虛擬/線性地址到分頁(yè)變換機(jī)構(gòu),以備進(jìn)行頁(yè)面地址變換操作
            VOID?APIENTRY?MemoaryKernel::Fn_Service_LoadVirtualAddress(UDWORD VirtualAddress)
            {
            ?this->NowLineAddress = VirtualAddress;
            ?if (IsPage == TRUE) {Fn_TranslateLineAddress();}
            }
            VOID?APIENTRY?MemoaryKernel::Fn_TranslateLineAddress()
            {?
            ?_asm
            ??{
            ???
            ???push?EBX
            ???push?ECX

            ???mov?EBX,this
            ???mov?EAX,[EBX]this.NowLineAddress
            ???mov?ECX,EAX

            ???and?EAX,0x0FFF //清空高24位得到頁(yè)內(nèi)偏移地址
            ???mov?[EBX]this.InPageOffset,EAX

            ???shr?ECX,12 //右移動(dòng)12位,得到頁(yè)號(hào)地址
            ???and?EAX,0x01FFF
            ???
            ???cmp?ECX,[EBX]this.MaxPageIndex
            ???jbe?OK
            ???mov?ECX,MAX_PAGE_NUMBER
            OK:
            ???mov?[EBX]this.PageAddressIndex,ECX
            ???pop?ECX
            ???pop?EBX
            ???
            ??}
            }

            VOID??APIENTRY?MemoaryKernel::Fn_Service_Init_MallocStack()
            {
            ?UDWORD?LoopCounter=0;
            ?UDWORD?PageAddressCounter = 0x0;
            ?UDWORD?OpAddress = StackEsp; //設(shè)置分配堆棧的開(kāi)始存儲(chǔ)地址
            ?DWORD?IsUsed;
            ?for(;PageAddressCounter<=MaxPageIndex;PageAddressCounter++)? //這個(gè)for循環(huán)構(gòu)造一個(gè)組長(zhǎng)為1024,
            ??{??????//共N組的成組鏈表用于分配和回收內(nèi)存頁(yè)
            ???IsUsed = Fn_Service_GetBitMap(PageAddressCounter);
            ???if(IsUsed == FALSE? && LoopCounter != 0x0400) //0x0400是1024 LoopCounter負(fù)責(zé)記錄是否分配了1024個(gè),是的話則設(shè)置新組
            ????{
            ?????Fn_WriteWord(OpAddress,PageAddressCounter); //ExHAL函數(shù),以字方式寫(xiě)寫(xiě)模擬物理內(nèi)存
            ?????LoopCounter++;
            ?????OpAddress=OpAddress+2; //每個(gè)堆棧項(xiàng)占2個(gè)字節(jié),因此這里+2
            ????}
            ???else
            ????{
            ?????if(LoopCounter == 0x0400) //等于1024 表示一個(gè)組已經(jīng)分配完了,該設(shè)置新組了
            ??????{
            ???????Fn_WriteDword(OpAddress,OpAddress+4);?//ExHAL函數(shù),以雙字(32bit)方式寫(xiě)模擬物理內(nèi)存?
            ????????????//系統(tǒng)中存放的組是連續(xù)的,因此新組的開(kāi)始地址就是當(dāng)前組完畢后的地址
            ???????PageAddressCounter--; //頁(yè)面地址減1,否則會(huì)在所有l(wèi)oopCounter=0x0400時(shí)丟失1Byte內(nèi)存... T_T
            ???????LoopCounter=0;
            ???????OpAddress=OpAddress+4;//因?yàn)槎褩5淖詈笠豁?xiàng)是指向新組的開(kāi)始地址,因此是雙字32bit 所以+4
            ??????}??
            ????}
            ??}
            ?Fn_WriteDword(OpAddress,MALLOC_STACK_END_FLAG);? //for循環(huán)完畢,寫(xiě)入堆棧結(jié)束標(biāo)志
            }

            UDWORD?APIENTRY?MemoaryKernel::Fn_Service_MallocOnePage()
            {
            ?UDWORD?Resault_Address;
            ?Resault_Address = (UDWORD)Fn_ReadWord(StackEsp);
            ?if ( Resault_Address == MALLOC_STACK_END_FLAG) //如果堆棧指針已經(jīng)指向了堆棧結(jié)尾標(biāo)志,說(shuō)明沒(méi)有可用物理內(nèi)存頁(yè)共分配了
            ??{
            ???ErrorCode=MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY;
            ???return MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY;
            ??}
            ?if (this->MallocCounter != 0x0400)
            ??{
            ???StackEsp=StackEsp+2;
            ???Fn_Service_SetBitMap(Resault_Address,USED);
            ???MallocCounter++; //分配次數(shù)計(jì)數(shù)器 每分配一次加1,1024次則讀入一個(gè)新堆棧
            ??}
            ?else
            ??{?//以下代碼重新取得新一組空閑頁(yè)面組的地址
            ???StackEsp = Fn_ReadDword(StackEsp); //將新組的開(kāi)始地址讀入堆棧操作指針
            ???
            ???if (StackEsp == MALLOC_STACK_END_FLAG) ////如果堆棧指針已經(jīng)指向了堆棧結(jié)尾標(biāo)志,
            ????{????//說(shuō)明沒(méi)有可用物理內(nèi)存頁(yè)共分配了
            ?????ErrorCode=MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY;
            ?????return MEMOARY_ALLOCATE_ERROR_NO_ENOUGH_MEMOARY;??
            ????}
            ???
            ???Resault_Address?= (UDWORD)(Fn_ReadWord(StackEsp)); //讀出新的空閑物理頁(yè)面號(hào)
            ???Fn_Service_SetBitMap(Resault_Address,USED); //設(shè)置該頁(yè)的分配狀態(tài)位
            ???StackEsp = StackEsp+2; //已經(jīng)分配了一個(gè)頁(yè)面 因此地址+2
            ???MallocCounter = 1; //已經(jīng)分配了一個(gè)頁(yè)面,因此為1而不是0
            ???GroupIndex++; //讀取了新組,因此+1
            ??}

            ?return?Resault_Address;

            }

            UDWORD?APIENTRY?MemoaryKernel::Fn_Service_FreeOnePage(UDWORD PageIndex)? //回收一個(gè)頁(yè)面
            {
            ?if (PageIndex <= SYSTEM_USE_END_PAGE_ADDRESS) //檢測(cè)即將釋放的地址的合法性
            ??{
            ???ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ???return?GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ??}

            ?if (PageIndex > MaxPageIndex) //檢測(cè)地址是否overflow
            ??{
            ???ErrorCode = GENERAL_PROTECT_ERROR_PAGE_INDEX_OVERFLOW;
            ???return?GENERAL_PROTECT_ERROR_PAGE_INDEX_OVERFLOW;
            ??}

            ?if (StackEsp==MEMOARY_STACK_BEGIN_STORE_LINE_ADDRESS) //簡(jiǎn)單的操作合法性檢測(cè)
            ??{
            ???ErrorCode = MEMOARY_FREE_ERROR_NO_MEMOARY_NEED_FREE;
            ???return MEMOARY_FREE_ERROR_NO_MEMOARY_NEED_FREE;
            ??}
            ?
            ?Fn_Service_GetBitMap(PageIndex); //進(jìn)一步在內(nèi)存使用狀態(tài)圖中查看該頁(yè)的當(dāng)前狀態(tài)
            ?_asm
            ??{
            ???cmp?EAX,USED //如果該頁(yè)已經(jīng)是空閑頁(yè),則不再對(duì)Malloc堆棧進(jìn)行操作
            ???jne?ErrorFree //以避免發(fā)生不同步的問(wèn)題
            ??}


            ?if (MallocCounter != 0) //!=0說(shuō)明當(dāng)前的組還未用完
            ??{?//先移動(dòng)指針,再讀出空閑物理頁(yè)面號(hào)
            ???StackEsp = StackEsp-2;
            ???Fn_WriteWord(StackEsp,PageIndex);
            ???Fn_Service_SetBitMap(PageIndex,UNUSE);
            ???MallocCounter--;
            ??}
            ?else
            ??{
            ???StackEsp = StackEsp-6;
            ???Fn_WriteWord(StackEsp,PageIndex);
            ???Fn_Service_SetBitMap(PageIndex,UNUSE);
            ???MallocCounter = 1023; //=1023是因?yàn)橐呀?jīng)分配了一個(gè)頁(yè)面 因此不是1024!
            ???GroupIndex--;
            ??}
            ?
            ?return?SUCCESS;
            ErrorFree:
            ?ErrorCode = MEMOARY_KERNEL_FREE_PAGE_FAILURE_PAGE_UNUSED;
            ?return?MEMOARY_KERNEL_FREE_PAGE_FAILURE_PAGE_UNUSED;
            }

            UDWORD?APIENTRY?MemoaryKernel::Fn_Service_GetErrorCode()
            {
            ?return?ErrorCode;
            }

            VOID?APIENTRY?MemoaryKernel::Fn_Service_GetMemoaryStatu()
            {
            ?U32?OpAddress=0x0;
            ?U32?LineAddress=0x0;
            ?U32?DisplayOpAddress=OpAddress+0x0F;
            ?CHAR?Pause=NULL;
            ?
            ?cout<<"This is Memoary Use Statu Viewer. :)"<<endl;
            ?cout<<"Command list:"<<endl;
            ?cout<<"A: Display All Memoary Address Use Statu."<<endl;
            ?cout<<"p: Display Memoary Address Use Statu on Group Mode."<<endl;
            ?cout<<"q: Exit."<<endl;
            ?cout.setf(ios::hex);
            ?do{
            ??if (Pause != 'a' && Pause !='A')
            ???{
            ????cout<<"Input Command Here: "<<flush;
            ????cin>>Pause;
            ???}

            ??if(Pause == 'A'||
            ???? Pause == 'a'||
            ???? Pause == 'p'||
            ???? Pause == 'P')
            ???{
            ????if(IsPage == TRUE)
            ?????{
            ??????cout<<"SYSTEM working in PageMode."<<endl;
            ??????for(OpAddress;OpAddress<=SYSTEM_USE_END_PAGE_ADDRESS;OpAddress++) //因?yàn)橐韵虏糠质茄h(huán)為了加速用了asm 其實(shí)就是算個(gè)地址
            ???????{
            ????????_asm?mov?EAX,[OpAddress]
            ????????_asm?shl?EAX,0x0C
            ????????_asm?mov?[LineAddress],EAX?
            ????????cout<<"PageIndexAddress: 0x0"<<OpAddress<<" (LineAddress: 0x0"<<LineAddress<<"-"<<flush;
            ????????_asm?add?DWORD ptr[LineAddress],0x0FFF
            ????????cout<<"0x0"<<LineAddress<<")"<<" is Used By SYSTEM."<<endl;
            ???????}
            ??????for(OpAddress;OpAddress<=(DisplayOpAddress);OpAddress++)
            ???????{
            ????????_asm
            ?????????{
            ??????????
            ??????????push?ECX
            ??????????
            ??????????mov?EAX,[OpAddress]
            ??????????mov?ECX,this
            ??????????mov?ECX,[ECX]this.MaxPageIndex
            ??????????cmp?EAX,ECX
            ??????????ja?DisplayFinish? //檢測(cè)到最大地址已經(jīng)顯示完畢則跳出顯示循環(huán)

            ??????????pop?ECX
            ??????????
            ?????????}
            ????????if (Fn_Service_GetBitMap(OpAddress) == USED)
            ?????????{
            ??????????_asm?mov?EAX,[OpAddress]
            ??????????_asm?shl?EAX,0x0C
            ??????????_asm?mov?[LineAddress],EAX?
            ??????????cout<<"PageIndexAddress: 0x0"<<OpAddress<<" (LineAddress: 0x0"<<LineAddress<<"-"<<flush;
            ??????????_asm?add?DWORD ptr[LineAddress],0x0FFF
            ??????????cout<<"0x0"<<LineAddress<<")"<<" is Used By User Programme"<<endl;
            ?????????}
            ????????else
            ?????????{?
            ??????????_asm?mov?EAX,[OpAddress]
            ??????????_asm?shl?EAX,0x0C
            ??????????_asm?mov?[LineAddress],EAX?
            ??????????cout<<"PageIndexAddress: 0x0"<<OpAddress<<" (LineAddress: 0x0"<<LineAddress<<"-"<<flush;
            ??????????_asm?add?DWORD ptr[LineAddress],0x0FFF
            ??????????cout<<"0x0"<<LineAddress<<")"<<" is Free."<<endl;
            ?????????}
            ???????}
            DisplayFinish:?
            ??????if (OpAddress < MaxPageIndex)
            ???????{
            ????????DisplayOpAddress = DisplayOpAddress+0x10;
            ???????}
            ??????else
            ???????{
            ????????Pause='q';
            ???????}
            ?????}
            ????else
            ?????{
            ??????cout<<"Now EmuSoloris SYSTEM Haltted."<<endl;
            ??????Pause = 'q';
            ?????}
            ???}
            ?}while(Pause != 'q' && Pause != 'Q');
            ?cout.setf(ios::dec);
            }


            BYTE?APIENTRY?MemoaryKernel::Fn_Service_ReadByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ????????UDWORD NewVirtualAddress)
            {
            ?UDWORD?CurrentPageBlock;
            ?BYTE?Resault=0;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);//加載虛擬地址到內(nèi)核
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex; //將地址調(diào)整到對(duì)應(yīng)的頁(yè)表項(xiàng)上
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock(); //取得對(duì)應(yīng)頁(yè)表項(xiàng)映射的物理空閑頁(yè)號(hào)
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS //對(duì)系統(tǒng)地址做保護(hù)
            ???jbe?AccessDeny
            ??}
            ??lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{?//這一段代碼對(duì)頁(yè)表項(xiàng)映射的合法性做進(jìn)一步檢測(cè)
            ???cmp?EAX,MEMOARY //標(biāo)志位是MEMOAY則合法
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX //映射的地址沒(méi)有overflow則完全合法
            ???ja?AddressError
            //AddressOK:?
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?EAX,ECX //EAX中放的就是轉(zhuǎn)換后的線性地址
            ???
            ???push?EAX
            ???call?Fn_ReadByte //讀取一個(gè)字節(jié)
            ???mov?BYTE ptr[Resault],AL
            ???
            ???pop?ECX
            ??}
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?return?Resault;
            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit?
            AccessDeny: //企圖訪問(wèn)系統(tǒng)使用的空間的出錯(cuò)處理
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:? //出錯(cuò)處理出口
            ?_asm
            ??{
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 0Ch?
            ??}
            }


            //實(shí)現(xiàn)思路同MemoaryKernel::Fn_Service_ReadByte函數(shù)
            VOID?APIENTRY?MemoaryKernel::Fn_Service_WriteByte(Lv1_MemoaryTable*?lpPageTableAddress,
            ????????UDWORD NewVirtualAddress,DWORD Value)
            {
            ?UDWORD?CurrentPageBlock;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);?
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex;
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock();
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS
            ???jbe?AccessDeny
            ??}?
            ?lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{
            ???cmp?EAX,MEMOARY
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap?
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX
            ???ja?AddressError
            ?
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?ECX,EAX

            ???mov?EAX,[Value]
            ???and?EAX,0x0FF
            ???push?EAX
            ???push?ECX
            ???call?Fn_WriteByte
            ???pop?ECX
            ??}
            ?
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?lpPageTableAddress->Fn_Service_SetIsModidy(TRUE);? //頁(yè)表對(duì)應(yīng)的物理頁(yè)是否被修改標(biāo)志為真
            ?_asm
            ??{
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h
            ??}
            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit
            AccessDeny:
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:?
            ?_asm
            ??{
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h?
            ??}
            }


            //實(shí)現(xiàn)思路同MemoaryKernel::Fn_Service_ReadByte函數(shù)
            WORD?APIENTRY?MemoaryKernel::Fn_Service_ReadWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ????????UDWORD NewVirtualAddress)
            {
            ?UDWORD?CurrentPageBlock;
            ?WORD?Resault;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);?
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex;
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock();
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS
            ???jbe?AccessDeny
            ??}
            ?lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{
            ???cmp?EAX,MEMOARY
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap??
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX
            ???ja?AddressError
            ?
            ??
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?EAX,ECX
            ???
            ???push?EAX
            ???call?Fn_ReadWord
            ???mov?WORD ptr[Resault],AX
            ???
            ???pop?ECX
            ??}
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?return?Resault;

            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit
            AccessDeny:
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:?
            ?_asm
            ??{
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 0Ch?
            ??}
            }


            //實(shí)現(xiàn)思路同MemoaryKernel::Fn_Service_ReadByte函數(shù)
            VOID?APIENTRY?MemoaryKernel::Fn_Service_WriteWord(Lv1_MemoaryTable*?lpPageTableAddress,
            ????????UDWORD NewVirtualAddress,DWORD Value)
            {
            ?UDWORD?CurrentPageBlock;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);?
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex;
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock();
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS
            ???jbe?AccessDeny
            ??}
            ?lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{
            ???cmp?EAX,MEMOARY
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap?
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX
            ???ja?AddressError
            ?
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?ECX,EAX
            ???
            ???mov?EAX,[Value]
            ???and?EAX,0x0FFFF
            ???push?EAX
            ???push?ECX
            ???call?Fn_WriteWord
            ??}
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?lpPageTableAddress->Fn_Service_SetIsModidy(TRUE); //設(shè)置是否修改標(biāo)志為真
            ?_asm
            ??{?
            ???pop?ECX
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h
            ??}
            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit
            AccessDeny:
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:?
            ?_asm
            ??{?
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h?
            ??}
            }

            //實(shí)現(xiàn)思路同MemoaryKernel::Fn_Service_ReadByte函數(shù)
            DWORD?APIENTRY?MemoaryKernel::Fn_Service_ReadDword(Lv1_MemoaryTable*?lpPageTableAddress,
            ???????? UDWORD NewVirtualAddress)
            {
            ?UDWORD?CurrentPageBlock;
            ?DWORD?Resault;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);?
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex;
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock();
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS
            ???jbe?AccessDeny
            ??}
            ?lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{
            ???cmp?EAX,MEMOARY
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap??
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX
            ???ja?AddressError
            ?
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?EAX,ECX
            ???
            ???push?EAX
            ???call?Fn_ReadDword
            ???mov?DWORD ptr[Resault],EAX
            ???
            ???pop?ECX
            ??}
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?return?Resault;

            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_READ_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit?
            AccessDeny:
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:
            ?_asm
            ??{
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 0Ch?
            ??}
            }


            //實(shí)現(xiàn)思路同MemoaryKernel::Fn_Service_ReadByte函數(shù)
            VOID?APIENTRY?MemoaryKernel::Fn_Service_WriteDword(Lv1_MemoaryTable* lpPageTableAddress,
            ????????UDWORD NewVirtualAddress,DWORD Value)
            {
            ?UDWORD?CurrentPageBlock;
            ?Fn_Service_LoadVirtualAddress(NewVirtualAddress);?
            ?lpPageTableAddress = lpPageTableAddress+PageAddressIndex;
            ?CurrentPageBlock = lpPageTableAddress->Fn_Service_GetPageBlock();
            ?_asm?
            ??{
            ???cmp?[CurrentPageBlock],SYSTEM_USE_END_PAGE_ADDRESS
            ???jbe?AccessDeny
            ??}
            ?lpPageTableAddress->Fn_Service_GetPageStatu();
            ?_asm
            ??{
            ???cmp?EAX,MEMOARY
            ???jne?AddressError
            ???cmp?EAX,SWAPPER
            ???je?INT_PageSwap?
            ???mov?EAX,this
            ???mov?EAX,[EAX]this.MaxPageIndex
            ???cmp?[CurrentPageBlock],EAX
            ???ja?AddressError
            ?
            ???push?ECX

            ???mov?EAX,[CurrentPageBlock]
            ???shl?EAX,0x0C
            ???mov?ECX,this
            ???mov?ECX,[ECX]this.InPageOffset
            ???and?ECX,0x0FFF
            ???add?ECX,EAX
            ???
            ???mov?EAX,[Value]
            ???push?EAX
            ???push?ECX
            ???call?Fn_WriteDword
            ??}
            ?lpPageTableAddress->Fn_Service_SetIsAccess(TRUE);? //頁(yè)是否被訪問(wèn)屬性設(shè)置為真
            ?lpPageTableAddress->Fn_Service_IncAccessCounter();? //頁(yè)訪問(wèn)計(jì)數(shù)器增加1
            ?lpPageTableAddress->Fn_Service_SetIsModidy(TRUE);? //設(shè)置是否修改標(biāo)志為真
            ?_asm
            ??{
            ???pop?ECX
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h?
            ??}
            INT_PageSwap:
            ?ErrorCode = MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY;
            ?_asm?mov?EAX,MEMOARY_KERNEL_INT_WRITE_PAGE_NOT_IN_MEMOARY
            ?_asm?jmp?Exit
            AccessDeny:
            ?ErrorCode = GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY;
            ?_asm?mov?EAX,GENERAL_PROTECT_ERROR_ACCESS_SYSTEM_MEMOARY
            ?_asm?jmp?Exit
            AddressError:?
            ?ErrorCode = MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION;
            ?_asm?mov?EAX,MEMOARY_KERNEL_READ_FAILURE_PAGE_NOT_ALLOCATION
            Exit:
            ?_asm
            ??{?
            ???pop???? edi
            ???pop???? esi
            ???pop???? ebx
            ???mov???? esp,ebp
            ???pop???? ebp
            ???ret???? 10h?
            ??}
            }

            上面的代碼如果編譯不正常,歡迎大家連續(xù)我。 :)


            ?

            亚洲综合伊人久久综合| 精品久久久久久中文字幕人妻最新| 2020最新久久久视精品爱| 97r久久精品国产99国产精| 国产成人久久激情91| 精品久久一区二区三区| 99久久国产热无码精品免费久久久久 | 亚洲精品成人久久久| 99久久做夜夜爱天天做精品| 国色天香久久久久久久小说 | 国内精品久久久久久久久电影网| 久久久久久无码国产精品中文字幕 | 91精品国产9l久久久久| 99久久国产热无码精品免费久久久久| 久久久久国产一级毛片高清板| 三级三级久久三级久久 | 亚洲va久久久噜噜噜久久男同 | 久久国产高潮流白浆免费观看| 日韩精品国产自在久久现线拍 | 久久国产精品99精品国产| 精品免费tv久久久久久久| 无码精品久久一区二区三区| 亚洲精品美女久久777777| 久久er热视频在这里精品| 欧美久久亚洲精品| 日韩人妻无码精品久久免费一| 91亚洲国产成人久久精品网址| 无码人妻久久一区二区三区蜜桃 | 无码人妻久久一区二区三区免费| 久久国产精品久久国产精品| 久久国产精品无| 国产午夜久久影院| 无码人妻少妇久久中文字幕| 国产产无码乱码精品久久鸭| 久久久久亚洲精品无码网址| 久久99精品久久久久久久不卡| 亚洲国产成人久久一区WWW| 国产精品久久久天天影视| 久久夜色精品国产亚洲| Xx性欧美肥妇精品久久久久久| 亚洲va久久久噜噜噜久久狠狠|