日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式軟件
[導(dǎo)讀]淺析在DOS實(shí)模式下直接存取4GB內(nèi)存

作為軟件開發(fā)人員,大多數(shù)對于保護(hù)模式都感到神秘和不易理解。本人在開發(fā)32位微內(nèi)核搶占式多線程操作系統(tǒng)過程中,深入了解到CPU的地址機(jī)理,在這里將分析CPU的工作原理,解開保護(hù)模式的神秘面紗,讀者將會發(fā)現(xiàn)保護(hù)模式其實(shí)與實(shí)模式一樣簡單和易于控制。在此基礎(chǔ)上用四五十行C語言程序做到進(jìn)出保護(hù)模式和在實(shí)模式之下直接訪問整個(gè)4GB內(nèi)存空間。

雖然有許多書籍對保護(hù)模式作解釋,但沒有一本能簡單明了地解釋清楚,冗長煩雜的術(shù)語讓人看著想打瞌睡,甚至還有許多用匯編寫的(可能根本不能運(yùn)行的)保護(hù)模式試驗(yàn)程序,事實(shí)上用C語言本身就可以做保護(hù)模式的進(jìn)出工作。

我們可能知道CPU上電后從ROM中的BIOS開始運(yùn)行,而Intel文檔卻說80x86CUP上電總是從最高內(nèi)存下16字節(jié)開始執(zhí)行,那么BIOS是處在內(nèi)存的最頂端64K(FFFF0000H)還是1M之下的64K(F0000H)處呢?事實(shí)上在這兩個(gè)地方都同時(shí)出現(xiàn)(可用后面存取4GB內(nèi)存的程序驗(yàn)證)。

為什么?為了弄清楚以上問題,首先要了解CPU是如何處理物理地址的?真的是在實(shí)模式下用段寄存器左移4位與偏移量相加,在保護(hù)模式下用段描述符中的基地址加偏移量而兩者是毫無關(guān)聯(lián)的嗎?答案是兩者其實(shí)是一樣的。當(dāng)Intel把80286推出時(shí)其地址空間變成了24位,從8086的20位到24位,十分自然地要加大段寄存器才行,實(shí)際上它們都被加大了,只是由于保護(hù)的原因加大的部分沒有被程序看見,到了80386之后地址又從24位加大到32位(80386SX是24位)。整個(gè)段寄存器如下圖所示:

@@12A08400.GIF;圖1@@

在8086中CPU只有“看得見部分”,從而也直接參與了地址形成運(yùn)算,但在80286之后,在“看不見部分”中已經(jīng)包含了地址值,“看得見部分”就退化為只是一個(gè)標(biāo)號再也不用參與地址形成運(yùn)算了。地址的形成總是從“不可看見部分”取出基址值與偏移相加形成地址。也就是說在實(shí)模式下當(dāng)一個(gè)段寄存器被裝入一個(gè)值時(shí),“看不見部分”的界限被設(shè)成FFFFH,基址部分才是要裝入值左移4位,屬性部分設(shè)成16位0特權(quán)級。這個(gè)過程與保護(hù)模式時(shí)裝入一個(gè)段存器是同理的,只是保護(hù)模式的“不可見部分”是從描述表中取值,而實(shí)模式是一套固定的過程。

對于CPU在形成地址時(shí),是沒有實(shí)模式與保護(hù)模式之分的,它只管用基址(“不可見部分”)去加上偏移量。實(shí)模式與保護(hù)模式的差別實(shí)際上只是保護(hù)處理部件是否工作得更精確而已,比如不允許代碼段的寫入。實(shí)模式下的段寄存裝入有固定的形成辦法從而也就不需要保護(hù)模式的“描述符”了,因此保持了與8086/8088的兼容性。而“描述符”也只是為了裝入段寄存器的“不可見部分”而設(shè)的。

從上面的“整個(gè)段寄存器”可見CPU的地址形成與“看得見部分”的當(dāng)前值毫無關(guān)系,這也解釋了為什么在剛進(jìn)入保護(hù)模式時(shí)后面的代碼依然被正確地運(yùn)行而這時(shí)代碼段寄存器CS的值卻還是進(jìn)入保護(hù)模式前的實(shí)模式值,或者從保護(hù)模式回到實(shí)模式時(shí)代碼段CS被改變之前程序是正常地工作,而不會“突變”到CS左移4位的地址上去,比如在保護(hù)模式時(shí)CS是08H的選擇器,到了實(shí)模式時(shí)CS還是08H但地址不會突然變成80H加上偏段量中去。因?yàn)榈刂返男纬刹焕頃渭拇嫫?ldquo;看得見部分”的當(dāng)前值,這一個(gè)值只是在被裝入時(shí)對CPU有用。

地址的形成與CPU的工作模式無關(guān),也就是說實(shí)模式與0特權(quán)級保護(hù)模式不分頁時(shí)是一模一樣的。明白了這一機(jī)理,在實(shí)模式下一樣可以處理通常被認(rèn)為只有在保護(hù)模式才能做的事,比如訪問整個(gè)機(jī)器的內(nèi)存??梢圆槐乩頃Wo(hù)模式下的眾多術(shù)語,或者更易于理解,如選擇器就是“看得見部分”,描述符是為了裝入“不可見部分”而設(shè)的。

作為驗(yàn)證CPU的這種機(jī)理,這里寫了一個(gè)實(shí)模式下訪問4GB內(nèi)存的C程序。有一些書籍也介紹有同樣功能的匯編程序,但它們都錯(cuò)誤地認(rèn)為是利用80386芯片的設(shè)計(jì)疏漏。實(shí)際上Intel本身就在使用這種辦法,使得CPU上電時(shí)能從FFFFFFF0H處開始第一條指令,這種技術(shù)在286之后的每一臺機(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í),基址就變了。

為了訪問4G內(nèi)存空間,必須有一個(gè)段寄存器的“不可見部分”的界限為4G-1,基址為0,這樣就包含了4GB內(nèi)存,不必理會可見部分的值。顯然要讓段寄存器在實(shí)模式下直接裝入這些值是不可能的。唯一的辦法是讓CPU進(jìn)入一會兒保護(hù)模式在裝入了段寄存器之后馬上回到實(shí)模式。

進(jìn)入保護(hù)模式十分簡單,只要建好GDT把CRO寄存器的位0置上1,CPU就在保護(hù)模式了,從前面所分析CPU地址形成機(jī)理可知,這時(shí)不必理會寄存器的“看得見部分”值是否合法,各種段寄存器是一樣可用的,就像沒進(jìn)保護(hù)模式一樣。在把一個(gè)包含有4GB地址空間的值裝入某個(gè)段寄存器之后就可返回實(shí)模式。

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

unsigned long GDT-Table[]={0,0, //空描述符,必須為零0x0000FFFF,0xCF9A00, //32位平面式代碼段0x0000FFFF,0xCF9200 } , //32位平面式數(shù)據(jù)段只是為了訪問數(shù)據(jù)的話只要2個(gè)GDT就足夠了,因?yàn)椴]有重裝代碼段,這里給出3個(gè)GDT只是為了完整性。

通常在進(jìn)入保護(hù)模式時(shí)要關(guān)閉所有的中斷,把IDTR的界限設(shè)置為0,CPU自動(dòng)關(guān)閉所有中斷,包括NMI,返回實(shí)模式后恢復(fù)IDTR并開中斷。

另外A20地址線的控制對于正確訪問整個(gè)內(nèi)存也很重要,在進(jìn)入保護(hù)模式前要讓8042打開A20地址線。

在這個(gè)例子里FS段寄存器設(shè)成可訪問4GB內(nèi)存的基址和界限,由于在DOS中很少有程序會用到GS、FS這兩個(gè)386增加的段寄存器,當(dāng)要讀寫4GB范圍中的任一個(gè)地方都可通過FS段來達(dá)到,直到FS在實(shí)模式下被重裝入沖掉為止。

這個(gè)例子在386SX、386DX、486上都運(yùn)行通過。例子里加有十分詳細(xì)的注釋,由于這一程序是用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)。如果有線性定址能力的VESA顯示卡(如TVGA9440)還可進(jìn)一步驗(yà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;

}

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉