zoukankan      html  css  js  c++  java
  • DOS下读取4GB内存

    好文章我收集下起来

    CPU上电后,从ROM 中的BIOS开始运行。
    BIOS是处在内存的最顶端64KB(FFFF0000H),还是1MB之下的64KB(F0000H)处呢?事实上,BIOS在这两个地方都同时出现。
    在保护模式时,CS是08H的选择子,到了实模式时,CS还是08H,但地址不会突然变成80H加上偏移量。
    也就是说,实模式与0特权级保护模式不分页时是一模一样的。
    所以,实模式下一样可以处理通常被认为只有在保护模式才能做的事,比如访问整个机器的内存。
    实际上,Intel本身就在使用这种办法,使得CPU上电时能从FFFFFFF0H处开始第一条指令。

    程序功能:

    1. 不需要在保护模式状态下就可以直接把386的4GB内存读出来;
    2. 利用此程序可直接在DOS中做物理设备的检测。
    3. 在DOS下,可根据此类方法将中断向量表移到任意位置,达到反跟踪或其他等目的。

    程序执行过程:

    程序运行后,等用户从键盘输入一个字符。

    当输入“Q”字符时,整个程序将退出;

    当输入“D”时,将在屏幕上显示一屏内存的数据:

    最左边为绝对地址,其后一列显示的是以十六进制位表示的内存的数据,后一列是数据所对应的ASCII码。

    代码关键分析:

    (1)IP=0000FFF0H

    CS∶EIP等于FFFFFFF0H。

    (2)段寄存器FS在实模式下无法装入4GB的地址和权限。

    所以让CPU进入一会儿保护模式,在装入了FS之后马上回到实模式。

    保护模式进入方式:建好GDT,把CR0寄存器的位0置上1。

    把一个包含有4GB地址空间的值装入FS之后,就可返回实模式。

    (3)预先可建好GDT如下:

    unsigned long GDT-Table[]=

    {

    0,0, //空描述符,必须为零

    0x0000FFFF,0xCF9A00, //32位平面式代码段

    0x0000FFFF,0xCF9200 //32位平面式数据段

    }

    (4)进入保护模式时要关闭所有的中断:把IDTR的界限设置为0,CPU自动关闭所有中断,包括NMI。

    返回实模式后恢复IDTR并开中断。

    (5)A20地址线的控制对于正确访问整个内存也很重要。

    在进入保护模式前,要让8042打开A20地址线,否则会出现4GB内存中的混乱。

    (6)此程序用BC 3.1编译连接,其连接器不能为DOS程序处理32位寄存器,所以直接在代码中加入操作码前缀0x66和地址前缀0x67,以便让DOS实模式下的16位程序可用32位寄存器和地址。程序的右边以注释形式给出等效的32位指令。

    注意:16位的指令中,mov al, byte ptr [BX]的指令码正好是32位的指令mov al, byte ptr[EDI]。

    附代码:

    #include <dos.h>

    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
    };

    //Save The IDTR before Enter Protect Mode.
    unsigned char OldIDT[6]={0};

    //NULL The IDTR,IDTR's Limit=0 will disable all
    //Interrupts,include NMI.
    unsigned char pdescr_tmp[6]={0};

    #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

    //**************************************
    //* Disable ints & Null IDT *
    //**************************************
    asm {
    CLI //Disable inerrupts
    SIDT OldIDT //Save OLD IDTR
    LIDT pdescr_tmp //Set up empty IDT.Disable any interrupts,Include NMI
    }

    //***************************************
    //* Load GDTR *
    //***************************************
    asm {
    //The right Code is Real,But BC++'s Linker NOT Work
    //with 32-bits Code.
    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 /////////////
    #include <stdio.h>
    /////////////////////////////////////////////////////////////
    //打印出Address指向的内存中的数据
    ///////////////////////////////////////////////////////////
    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");
    }

    }

    int main( void )
    {
    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;
    }
    签名:wak免费电影http://www.wak99.com.
  • 相关阅读:
    LeetCode Flatten Binary Tree to Linked List
    LeetCode Longest Common Prefix
    LeetCode Trapping Rain Water
    LeetCode Add Binary
    LeetCode Subsets
    LeetCode Palindrome Number
    LeetCode Count and Say
    LeetCode Valid Parentheses
    LeetCode Length of Last Word
    LeetCode Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/anakin/p/2288792.html
Copyright © 2011-2022 走看看