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.
  • 相关阅读:
    Mysql 删除表
    Mysql 创建表
    Mysql left join
    Qt(Mac) 进程的启动
    Mysql update
    Mysql insert
    Mysql select
    Mysql INNER JOIN
    Mysql 别名
    Mysql 排序
  • 原文地址:https://www.cnblogs.com/anakin/p/2288792.html
Copyright © 2011-2022 走看看