#include <STDIO.H>    
unsigned char OldIDT [6]={0}; 
unsigned char pdescr_tmp[6]={0}; 
unsigned   long   GDT_Table[]= 
{ 
0,0,   //NULL   -   00H 
0x0000FFFF,0x00CF9A00,   //Code32   -   08h   Base=0   Limit=4G-1   Size=4G 
0x0000FFFF,0x00CF9200   //Data32   -   10h   Base=0   Limit=4G-1   Size=4G 
};
#define KeyWait()   {while(inportb(0x64)&2);}    

void    A20Enable(void)   
{   
    KeyWait();   
    outportb(0x64,0xD1);   
    KeyWait();   
    outportb(0x60,0xDF);    //Enable A20 with 8042.    
    KeyWait();   
    outportb(0x64,0xFF);   
    KeyWait();   
}   
void    LoadFSLimit4G(void)   
{   
    A20Enable();        //Enable A20    
    asm {
   		CLI                 
   	  	SIDT    OldIDT      
  	    LIDT    pdescr_tmp 
        db  0x66        //32 bit Operation Prefix in 16 Bit DOS.    
        MOV CX,DS               //MOV   ECX,DS    
        db  0x66                //Get Data segment physical Address    
        SHL CX,4                //SHL   ECX,4    
        MOV word ptr pdescr_tmp[0],(3*8-1)  //MOV   word ptr pdescr_tmp[0],(3*8-1)    
        db  0x66   
        XOR AX,AX               //XOR   EAX,EAX    
        MOV AX,offset GDT_Table     //MOV   AX,offset GDT_Table    
        db  0x66   
        ADD AX,CX               //ADD   EAX,ECX    
        MOV word ptr pdescr_tmp[2],AX   //GDTR Base high16 bits    
        db  0x66   
        SHR AX,16               //SHR   EAX,16    
        MOV word ptr pdescr_tmp[4],AX   //GDTR Base high16 bits    
        LGDT    pdescr_tmp          //Load GDTR    
        }   
    //**************************************    
    //*  Enter 32 bit Flat Protected Mode  *    
    //**************************************    
    //  Set CR0 Bit-0 to 1 Enter 32 Bit Protection    
    //Mode,And NOT Clear machine perform cache,It Meaning    
    //the after Code HAD Ready To RUN in 32 Bit Flat Mode,    
    //Then Load Flat Selector to FS and Description into it's    
    //Shadow register,After that,ShutDown Protection Mode    
    //And ReEnter Real Mode immediately.    
    //  The FS holds Base=0 Size=4G Description and    
    //it can Work in Real Mode as same as Pretect Mode,    
    //untill FS be reloaded.    
    //  In that time All the other Segment Registers are    
    //Not Changed,except FS.(They are ERROR Value holded in CPU).    
    asm {   
        MOV DX,0x10         //The Data32 Selector    
        db  0x66,0x0F,0x20,0xC0 //MOV   EAX,CR0    
        db  0x66   
        MOV BX,AX           //MOV   EBX,EAX    
        OR  AX,1   
        db  0x66,0x0F,0x22,0xC0 //MOV   CR0,EAX //Set Protection enable bit    
        JMP Flush   
        }               //Clear machine perform cache.    
    Flush:  //Now In Flat Mode,But The CS is Real Mode Value.    
    asm {   //And it's attrib is 16-Bit Code Segment.    
        db  0x66   
        MOV AX,BX           //MOV   EAX,EBX    
        db  0x8E,0xE2       //MOV   FS,DX   //Load FS now    
        db  0x66,0x0F,0x22,0xC0 //MOV   CR0,EAX //Return Real Mode.Now FS's Base=0 Size=4G    
        LIDT    OldIDT          //LIDT  OldIDT  //Restore IDTR    
        STI             //STI       //Enable INTR    
        }   
}   
//With FS can Access All 4G Memory Now.But if FS be reloaded in Real Mode    
//It's Limit will Be Set to FFFFh(Size=64K),then Can not used it to Access    
//4G bytes Memory Again,Because FS is Segment:Offset Memory type after that.    
//If Use it to Access large than 64K will generate Execption 0D.    
unsigned char   ReadByte(unsigned long Address)   
{   
    asm db  0x66   
    asm mov di,word ptr Address //MOV   EDI,Address    
    asm db  0x67            //32 bit Address Prefix    
    asm db  0x64            //FS:    
    asm mov al,byte ptr [BX]    //=MOV AL,FS:[EDI]    
    return  _AL;   
}   
unsigned char   WriteByte(unsigned long Address)   
{   
    asm db  0x66   
    asm mov di,word ptr Address //MOV   EDI,Address    
    asm db  0x67            //32 bit Address Prefix    
    asm db  0x64            //FS:    
    asm mov byte ptr [BX],al    //=MOV FS:[EDI],AL    
    return  _AL;   
}   
///////////////// Don't Touch Above Code ///////////////    
////////////////////////////////////////////////////////    

void    Dump4G(unsigned long Address)   
{   
    int i;   
    int j;   
    for(i=0;i<20;i++)   
        {   
        printf("%08lX: ",(Address+i*16));   
        for(j=0;j<16;j++)   
            printf("%02X ",ReadByte(Address+i*16+j));   
        printf("    ");   
        for(j=0;j<16;j++)   
            {   
            if(ReadByte(Address+i*16+j)<0x20) printf(".");   
            else    printf("%c",ReadByte(Address+i*16+j));   
            }   
        printf("\n");   
        }   
}   
main()   
{   
    char        KeyBuffer[256];   
    unsigned long   Address=0;   
    unsigned long   tmp;   
       
    LoadFSLimit4G();   
    printf("====Designed By Southern.1995.7.17====\n");   
    printf("Now you can Access The Machine All 4G Memory.\n");   
    printf("Input the Start Memory Physical to DUMP.\n");   
    printf("Press D to Cuntinue DUMP,0 to End & Quit.\n");   
    do  {   
        printf("-");   
        gets(KeyBuffer);   
        sscanf(KeyBuffer,"%lX",&tmp);   
        if(KeyBuffer[0]=='q') break;   
        if(KeyBuffer[0]=='d') Address+=(20*16);   
        else Address=tmp;   
        Dump4G(Address);   
        }while(Address!=0);   
    return 0;   
}   
