日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

DOS下读取4GB内存——梁肇新代码分析

發(fā)布時(shí)間:2023/12/29 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DOS下读取4GB内存——梁肇新代码分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

程序原理:

?

CPU上電后,從ROM 中的BIOS開(kāi)始運(yùn)行。
BIOS是處在內(nèi)存的最頂端64KB(FFFF0000H),還是1MB之下的64KB(F0000H)處呢?事實(shí)上,BIOS在這兩個(gè)地方都同時(shí)出現(xiàn)。
在保護(hù)模式時(shí),CS是08H的選擇子,到了實(shí)模式時(shí),CS還是08H,但地址不會(huì)突然變成80H加上偏移量。
也就是說(shuō),實(shí)模式與0特權(quán)級(jí)保護(hù)模式不分頁(yè)時(shí)是一模一樣的。
所以,實(shí)模式下一樣可以處理通常被認(rèn)為只有在保護(hù)模式才能做的事,比如訪(fǎng)問(wèn)整個(gè)機(jī)器的內(nèi)存。
實(shí)際上,Intel本身就在使用這種辦法,使得CPU上電時(shí)能從FFFFFFF0H處開(kāi)始第一條指令。

程序功能:

  • 不需要在保護(hù)模式狀態(tài)下就可以直接把386的4GB內(nèi)存讀出來(lái);
  • 利用此程序可直接在DOS中做物理設(shè)備的檢測(cè)。
  • 在DOS下,可根據(jù)此類(lèi)方法將中斷向量表移到任意位置,達(dá)到反跟蹤或其他等目的。
  • 程序執(zhí)行過(guò)程:

      程序運(yùn)行后,等用戶(hù)從鍵盤(pán)輸入一個(gè)字符。

      當(dāng)輸入“Q”字符時(shí),整個(gè)程序?qū)⑼顺?#xff1b;

      當(dāng)輸入“D”時(shí),將在屏幕上顯示一屏內(nèi)存的數(shù)據(jù):

        最左邊為絕對(duì)地址,其后一列顯示的是以十六進(jìn)制位表示的內(nèi)存的數(shù)據(jù),后一列是數(shù)據(jù)所對(duì)應(yīng)的ASCII碼。

    代碼關(guān)鍵分析:

    ?

    (1)IP=0000FFF0H

    ?

    CS∶EIP等于FFFFFFF0H。

    ?

    (2)段寄存器FS在實(shí)模式下無(wú)法裝入4GB的地址和權(quán)限。

    所以讓CPU進(jìn)入一會(huì)兒保護(hù)模式,在裝入了FS之后馬上回到實(shí)模式。

    ?

    保護(hù)模式進(jìn)入方式:建好GDT,把CR0寄存器的位0置上1。

    把一個(gè)包含有4GB地址空間的值裝入FS之后,就可返回實(shí)模式。

    ?

    (3)預(yù)先可建好GDT如下:

    ?

    unsigned long GDT-Table[]=

    {

      0,0,??????????????????? ??? //空描述符,必須為零

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

      0x0000FFFF,0xCF9200 ? ? ? ? //32位平面式數(shù)據(jù)段

    } ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    ?

    (4)進(jìn)入保護(hù)模式時(shí)要關(guān)閉所有的中斷:把IDTR的界限設(shè)置為0,CPU自動(dòng)關(guān)閉所有中斷,包括NMI。

    返回實(shí)模式后恢復(fù)IDTR并開(kāi)中斷。

    ?

    (5)A20地址線(xiàn)的控制對(duì)于正確訪(fǎng)問(wèn)整個(gè)內(nèi)存也很重要。

    在進(jìn)入保護(hù)模式前,要讓8042打開(kāi)A20地址線(xiàn),否則會(huì)出現(xiàn)4GB內(nèi)存中的混亂。

    (6)此程序用BC 3.1編譯連接,其連接器不能為DOS程序處理32位寄存器,所以直接在代碼中加入操作碼前綴0x66和地址前綴0x67,以便讓DOS實(shí)模式下的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指向的內(nèi)存中的數(shù)據(jù)
    ///
    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;
    }



    轉(zhuǎn)載于:https://www.cnblogs.com/gengzhikui/archive/2011/12/15/2288605.html

    總結(jié)

    以上是生活随笔為你收集整理的DOS下读取4GB内存——梁肇新代码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。