• <sub id="h4knl"><ol id="h4knl"></ol></sub>
    <sup id="h4knl"></sup>
      <sub id="h4knl"></sub>

      <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
      1. <strong id="h4knl"></strong>

      2. 計(jì)算機(jī)畢業(yè)論文-在DOS實(shí)模式下直接存取4GB內(nèi)存

        時(shí)間:2024-07-21 03:50:23 計(jì)算機(jī)畢業(yè)論文 我要投稿
        • 相關(guān)推薦

        計(jì)算機(jī)畢業(yè)論文-在DOS實(shí)模式下直接存取4GB內(nèi)存


           作為軟件開(kāi)發(fā)人員,大多數(shù)對(duì)于保護(hù)模式都感到神秘和不易理解。本人在開(kāi)發(fā)32位微內(nèi)核搶占式多線(xiàn)程操作系統(tǒng)過(guò)程中,深入了解到CPU的地址機(jī)理,在這里將分析CPU的工作原理,解開(kāi)保護(hù)模式的神秘面紗,讀者將會(huì)發(fā)現(xiàn)保護(hù)模式其實(shí)與實(shí)模式一樣簡(jiǎn)單和易于控制。在此基礎(chǔ)上用四五十行C語(yǔ)言程序做到進(jìn)出保護(hù)模式和在實(shí)模式之下直接訪(fǎng)問(wèn)整個(gè)4GB內(nèi)存空間。
        雖然有許多書(shū)籍對(duì)保護(hù)模式作解釋?zhuān)珱](méi)有一本能簡(jiǎn)單明了地解釋清楚,冗長(zhǎng)煩雜的術(shù)語(yǔ)讓人看著想打瞌睡,甚至還有許多用匯編寫(xiě)的(可能根本不能運(yùn)行的)保護(hù)模式試驗(yàn)程序,事實(shí)上用C語(yǔ)言本身就可以做保護(hù)模式的進(jìn)出工作。
        我們可能知道CPU上電后從ROM中的BIOS開(kāi)始運(yùn)行,而Intel文檔卻說(shuō)80x86CUP上電總是從最高內(nèi)存下16字節(jié)開(kāi)始執(zhí)行,那么BIOS是處在內(nèi)存的最頂端64K(FFFF0000H)還是1M之下的64K(F0000H)處呢?事實(shí)上在這兩個(gè)地方都同時(shí)出現(xiàn)(可用后面存取4GB內(nèi)存的程序驗(yàn)證)。
        為什么?為了弄清楚以上問(wèn)題,首先要了解CPU是如何處理物理地址的?真的是在實(shí)模式下用段寄存器左移4位與偏移量相加,在保護(hù)模式下用段描述符中的基地址加偏移量而兩者是毫無(wú)關(guān)聯(lián)的嗎?答案是兩者其實(shí)是一樣的。當(dāng)Intel把80286推出時(shí)其地址空間變成了24位,從8086的20位到24位,十分自然地要加大段寄存器才行,實(shí)際上它們都被加大了,只是由于保護(hù)的原因加大的部分沒(méi)有被程序看見(jiàn),到了80386之后地址又從24位加大到32位(80386SX是24位)。整個(gè)段寄存器如下圖所示:
        @@12A08400.GIF;圖1@@
        在8086中CPU只有“看得見(jiàn)部分”,從而也直接參與了地址形成運(yùn)算,但在80286之后,在“看不見(jiàn)部分”中已經(jīng)包含了地址值,“看得見(jiàn)部分”就退化為只是一個(gè)標(biāo)號(hào)再也不用參與地址形成運(yùn)算了。地址的形成總是從“不可看見(jiàn)部分”取出基址值與偏移相加形成地址。也就是說(shuō)在實(shí)模式下當(dāng)一個(gè)段寄存器被裝入一個(gè)值時(shí),“看不見(jiàn)部分”的界限被設(shè)成FFFFH,基址部分才是要裝入值左移4位,屬性部分設(shè)成16位0特權(quán)級(jí)。這個(gè)過(guò)程與保護(hù)模式時(shí)裝入一個(gè)段存器是同理的,只是保護(hù)模式的“不可見(jiàn)部分”是從描述表中取值,而實(shí)模式是一套固定的過(guò)程。
        對(duì)于CPU在形成地址時(shí),是沒(méi)有實(shí)模式與保護(hù)模式之分的,它只管用基址(“不可見(jiàn)部分”)去加上偏移量。實(shí)模式與保護(hù)模式的差別實(shí)際上只是保護(hù)處理部件是否工作得更精確而已,比如不允許代碼段的寫(xiě)入。實(shí)模式下的段寄存裝入有固定的形成辦法從而也就不需要保護(hù)模式的“描述符”了,因此保持了與8086/8088的兼容性。而“描述符”也只是為了裝入段寄存器的“不可見(jiàn)部分”而設(shè)的。
        從上面的“整個(gè)段寄存器”可見(jiàn)CPU的地址形成與“看得見(jiàn)部分”的當(dāng)前值毫無(wú)關(guān)系,這也解釋了為什么在剛進(jìn)入保護(hù)模式時(shí)后面的代碼依然被正確地運(yùn)行而這時(shí)代碼段寄存器CS的值卻還是進(jìn)入保護(hù)模式前的實(shí)模式值,或者從保護(hù)模式回到實(shí)模式時(shí)代碼段CS被改變之前程序是正常地工作,而不會(huì)“突變”到CS左移4位的地址上去,比如在保護(hù)模式時(shí)CS是08H的選擇器,到了實(shí)模式時(shí)CS還是08H但地址不會(huì)突然變成80H加上偏段量中去。因?yàn)榈刂返男纬刹焕頃?huì)段寄存器“看得見(jiàn)部分”的當(dāng)前值,這一個(gè)值只是在被裝入時(shí)對(duì)CPU有用。
        地址的形成與CPU的工作模式無(wú)關(guān),也就是說(shuō)實(shí)模式與0特權(quán)級(jí)保護(hù)模式不分頁(yè)時(shí)是一模一樣的。明白了這一機(jī)理,在實(shí)模式下一樣可以處理通常被認(rèn)為只有在保護(hù)模式才能做的事,比如訪(fǎng)問(wèn)整個(gè)機(jī)器的內(nèi)存?梢圆槐乩頃(huì)保護(hù)模式下的眾多術(shù)語(yǔ),或者更易于理解,如選擇器就是“看得見(jiàn)部分”,描述符是為了裝入“不可見(jiàn)部分”而設(shè)的。
        作為驗(yàn)證CPU的這種機(jī)理,這里寫(xiě)了一個(gè)實(shí)模式下訪(fǎng)問(wèn)4GB內(nèi)存的C程序。有一些書(shū)籍也介紹有同樣功能的匯編程序,但它們都錯(cuò)誤地認(rèn)為是利用80386芯片的設(shè)計(jì)疏漏。實(shí)際上Intel本身就在使用這種辦法,使得CPU上電時(shí)能從FFFFFFF0H處開(kāi)始第一條指令,這種技術(shù)在286之后的每一臺(tái)機(jī)器每一次冷啟動(dòng)時(shí)都使用,只是我們不知道罷了。CPU上電也整個(gè)代碼段寄存器是這樣的:
        @@12A08401.GIF;圖2@@
        EIP=0000FFF0H
        這樣CS∶EIP形成了FFFFFFF0H的物理地址,當(dāng)CPU進(jìn)行一次遠(yuǎn)跳轉(zhuǎn)重新裝入CS時(shí),基址就變了。
        為了訪(fǎng)問(wèn)4G內(nèi)存空間,必須有一個(gè)段寄存器的“不可見(jiàn)部分”的界限為4G-1,基址為0,這樣就包含了4GB內(nèi)存,不必理會(huì)可見(jiàn)部分的值。顯然要讓段寄存器在實(shí)模式下直接裝入這些值是不可能的。唯一的辦法是讓CPU進(jìn)入一會(huì)兒保護(hù)模式在裝入了段寄存器之后馬上回到實(shí)模式。
        進(jìn)入保護(hù)模式十分簡(jiǎn)單,只要建好GDT把CRO寄存器的位0置上1,CPU就在保護(hù)模式了,從前面所分析CPU地址形成機(jī)理可知,這時(shí)不必理會(huì)寄存器的“看得見(jiàn)部分”值是否合法,各種段寄存器是一樣可用的,就像沒(méi)進(jìn)保護(hù)模式一樣。在把一個(gè)包含有4GB地址空間的值裝入某個(gè)段寄存器之后就可返回實(shí)模式。
        預(yù)先可建好GDT如下:
        unsigned long GDT-Table[]={0,0, //空描述符,必須為零0x0000FFFF,0xCF9A00, //32位平面式代碼段0x0000FFFF,0xCF9200 } , //32位平面式數(shù)據(jù)段只是為了訪(fǎng)問(wèn)數(shù)據(jù)的話(huà)只要2個(gè)GDT就足夠了,因?yàn)椴](méi)有重裝代碼段,這里給出3個(gè)GDT只是為了完整性。
        通常在進(jìn)入保護(hù)模式時(shí)要關(guān)閉所有的中斷,把IDTR的界限設(shè)置為0,CPU自動(dòng)關(guān)閉所有中斷,包括NMI,返回實(shí)模式后恢復(fù)IDTR并開(kāi)中斷。
        另外A20地址線(xiàn)的控制對(duì)于正確訪(fǎng)問(wèn)整個(gè)內(nèi)存也很重要,在進(jìn)入保護(hù)模式前要讓8042打開(kāi)A20地址線(xiàn)。
        在這個(gè)例子里FS段寄存器設(shè)成可訪(fǎng)問(wèn)4GB內(nèi)存的基址和界限,由于在DOS中很少有程序會(huì)用到GS、FS這兩個(gè)386增加的段寄存器,當(dāng)要讀寫(xiě)4GB范圍中的任一個(gè)地方都可通過(guò)FS段來(lái)達(dá)到,直到FS在實(shí)模式下被重裝入沖掉為止。
        這個(gè)例子在386SX、386DX、486上都運(yùn)行通過(guò)。例子里加有十分詳細(xì)的注釋?zhuān)捎谶@一程序是用BC 3.1編譯連接的,而其連接器不能為DOS程序處理32位寄存器,所以直接在代碼中加入操作碼前綴0x66和地址前綴0x67,以便讓DOS實(shí)模式下的16位程序可用32位寄存器和地址。程序的右邊以注釋形式給出等效的32位指令。要注意16位的指令中mov al, byte ptr [BX]的指令碼正好是32位的指令mov al, byte ptr[EDI]。
        讀者可用這個(gè)程序驗(yàn)證BIOS是否同時(shí)在兩個(gè)區(qū)域出現(xiàn)。如果有線(xiàn)性定址能力的VESA顯示卡(如TVGA9440)還可進(jìn)一步驗(yàn)證線(xiàn)性顯示緩沖區(qū)在1MB之上的工作情況。
        #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
        };
        unsigned char OldIDT [6]={0}; //Save The IDTR before Enter Protect Mode.
        unsigned char pdescr-tmp [6]={0}; //NULL The IDTR s Limit=0 CPU will
        // disable all Interrupts, include NMI.
        #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.
        //***
        Lodd GDTR
        //***
        asm{ // The right Code is Real, But BC++ s Linker NOT
        // Work with 32bits 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 low16 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
        //****
        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 CRO,EAX // Set Protection enable bit
        JMP Flsuh
        } //Clear machine perform cache.
        flush: // Now In Flat Mode, But The CS is Real Mode Value.
        asm { //And it s attrib is 16Bit Code Segment.
        db 0x66
        MOV AX,BX //MOV EAX,EBX
        db 0x8E,0xE2 //MOV FS,DX
        //Load FS Base=0 Size=4G now
        db 0x66,0x0F,0x22,0xC0 //MOV CRO,EAX
        //Return Real Mode.
        LIDT OldIDT //LIDT OldIDT //Restore IDTR
        STI // STI //Enable INTR
        }
        }
        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>
        void Dump4G (unsigned long Address)
        {
        int i;
        int j;
        for (i=0; i<20; i++)
        {
        printf (“%081X: ”, (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 ()
        {
        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 ("-");
        scanf ("%IX", &tmp);
        if (tmp==0x0d) Address+=(20*16);
        else Address=tmp;
        Dump4G (Address);
        }while (Address !=0);
        return 0;


        【計(jì)算機(jī)畢業(yè)論文-在DOS實(shí)模式下直接存取4GB內(nèi)存】相關(guān)文章:

        在DOS實(shí)模式下直接存取4GB內(nèi)存03-19

        DOS真彩色模式下真彩色圖像顯示技術(shù)03-03

        DOS下DSP播音的編程03-03

        在 DOS 下使用Windows *.WAV 文件03-03

        DOS界面下通用圖形編輯軟件的設(shè)計(jì)03-06

        漫談?wù)w項(xiàng)目驅(qū)動(dòng)模式下計(jì)算機(jī)軟件人才培養(yǎng)模式03-01

        計(jì)算機(jī)網(wǎng)絡(luò)環(huán)境下教學(xué)模式的評(píng)價(jià)03-21

        CDIO模式下計(jì)算機(jī)專(zhuān)業(yè)教學(xué)改革探析03-26

        學(xué)生為中心的教學(xué)模式下計(jì)算機(jī)教學(xué)應(yīng)用論文11-13

        国产高潮无套免费视频_久久九九兔免费精品6_99精品热6080YY久久_国产91久久久久久无码
      3. <sub id="h4knl"><ol id="h4knl"></ol></sub>
        <sup id="h4knl"></sup>
          <sub id="h4knl"></sub>

          <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
          1. <strong id="h4knl"></strong>

          2. 日本在线日韩在线一区二区 | 婷婷色六月综合缴情 | 欧美精品剧情一区二区三区 | 亚洲国产91高清 | 精品综合一区二区三区 | 无套内谢的新婚少妇国语播放 |