突破DOS實模式限制直接訪問4GB內存

字號:

PM_Service:
     Mov AX,16
     Mov _seg,AX
     Mov EBX,CR0
     And EBX,0fffffffeh
     Mov CR0,EBX
     DB 0eah
     DW Real_Service
     DW seg Real_Service
    Real_Service:
     Lgdt FWORD Ptr [Old_GDTR]
     Popfd ;恢復現(xiàn)場
     Popad
     Pop ES
     Pop DS
     Jmp _Exit
    MyGdt DQ 0
     DW -1,0,9a00h,0
     DW -1,0,9200h,0cfh
     DQ 0
    Old_GDTR DW 0,0,0
    GDTR DW 0,0,0
    _Exit:
     Endm
    在這里為了方便我只把FS改成4GB段,讀者可以按需要自行決定使用哪個段寄存器。只要將這段代碼拷貝到你的程序中,然后在開始的時候調用它,就可以通過該段寄存器直接訪問大內存了,爽吧!
    最后還有一點一定要注意:如果你的程序運行時有任何擴展內存管理程序存在(HIMEM、EMM386等)都要千萬小心,因為很容易會破壞到它們的內部數(shù)據(jù)或其他程序的數(shù)據(jù),如果是這樣就只有死機一條路可走了。切記切記!我的建議是從內存頂端開始使用擴展內存。這時破壞其他數(shù)據(jù)的可能要小一些。
    local MyGdt,PM_Service,Old_GDTR,GDTR,Real_Service,MyGdt
    local _Exit
     Push DS
     Push ES
     Pushad
     Pushfd ;保護現(xiàn)場
     Sub EBX,EBX
     Mov BX,CS
     Mov DS,BX
     Shl EBX,4
     Push EBX
     Rol EBX,8
     Mov BYTE Ptr MyGdt[8+7],BL
     Mov BL,BYTE Ptr MyGdt[8+5]
     Ror EBX,8
     Mov DWORD Ptr MyGdt[8+2],EBX
     Pop EBX
     lea EBX,[EBX+MyGdt]
     Mov DWORD Ptr [GDTR+2],EBX
     Mov WORD Ptr [GDTR],31 ;建立新的GDTR
     Cli
     Sgdt FWORD Ptr [Old_GDTR] ;保存舊的GDTR
     Lgdt FWORD Ptr [GDTR] ;設置新的GDTR
     Mov EBX,CR0
     Or BL,1
     Mov CR0,EBX ;進入保護模式
     DB 0eah
     DW PM_Service
     DW 8 ;跳轉到保護模式代碼執(zhí)行|
    PM_Service:
     Mov AX,16
     Mov _seg,AX
     Mov EBX,CR0
     And EBX,0fffffffeh
     Mov CR0,EBX
     DB 0eah
     DW Real_Service
     DW seg Real_Service
    Real_Service:
     Lgdt FWORD Ptr [Old_GDTR]
     Popfd ;恢復現(xiàn)場
     Popad
     Pop ES
     Pop DS
     Jmp _Exit
    MyGdt DQ 0
     DW -1,0,9a00h,0
     DW -1,0,9200h,0cfh
     DQ 0
    Old_GDTR DW 0,0,0
    GDTR DW 0,0,0
    _Exit:
     Endm
    在這里為了方便我只把FS改成4GB段,讀者可以按需要自行決定使用哪個段寄存器。只要將這段代碼拷貝到你的程序中,然后在開始的時候調用它,就可以通過該段寄存器直接訪問大內存了,爽吧!
    最后還有一點一定要注意:如果你的程序運行時有任何擴展內存管理程序存在(HIMEM、EMM386等)都要千萬小心,因為很容易會破壞到它們的內部數(shù)據(jù)或其他程序的數(shù)據(jù),如果是這樣就只有死機一條路可走了。切記切記!我的建議是從內存頂端開始使用擴展內存。這時破壞其他數(shù)據(jù)的可能要小一些。