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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

程序原理:

?

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

程序功能:

  • 不需要在保護模式狀態下就可以直接把386的4GB內存讀出來;
  • 利用此程序可直接在DOS中做物理設備的檢測。
  • 在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;
    }



    轉載于:https://www.cnblogs.com/gengzhikui/archive/2011/12/15/2288605.html

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。