cpu執行第一條指令時情形

2021-05-01 04:39:50 字數 3526 閱讀 7166

cpu執行的第一條指令不在記憶體中,眾所周知,記憶體是由ram組成的 ,而ram不斷電,可以儲存資訊,一旦斷電,ram中的資訊將會丟失,所以cpu要執行的第一條指令被固化在rom中

以前8086年代,由於記憶體是1m的,所以rom被編址在1m的最後的64k 中,所以它的段位址是0xffff0,這樣就不至於不ram分成兩個部分,就是將cs設定成0xf000,cpu執行的bios第一條指令的位址 是:0xf000:fff0h,這樣使得韌體的位址在定址空間靠後的位置16個位元組處,這是一條跳轉指令,向前調轉到乙個地方,然後開始執行,啟動**由

jmp f000 : ***x

中的偏移

***x

來把握,如果使用得多,

***x

就小,使用得少,

***x

就大,這樣使啟動**盡量靠後,而不浪費多餘的位址空間,由於位址空間安排在最後,也不會把整個位址空間隔離成兩段。

而出現80386以後,記憶體已經大於1m,所以

如果把冷啟動韌體編址在

f000h

段內,就會把整個位址空間隔離成不連續的兩段,一段是

f000h

以前的位址,一段是

1m以後的位址,這很不方便。

intel

採用的辦法是,還是預設將執行啟動**的

bios rom

編址在系統可定址空間的最後(如32位

x86機的話,這段位址就位於

4gb的最後乙個

64k內),在系統復位時,

cpu進入實模式,並將

cs暫存器設定成

f000h

,而將它的

shadow register

的base

設定成ffff0000h

(理論上正常情況下cs為

f000h

的話,其

shadow register

的base

應該設定成

000f

0000h

,但intel

有意識的將高

12位觸發成

1了,除了這樣他也沒有什麼好辦法讓機器一啟動就跑道

4gb那麼高的位址上去執行),而偏移量

eip置成

0000fff0h

,所以機器執行的第一條指令的韌體安排的實體地址顯然就變成了

fffffff0h

。bios

**和以前還是要相容的,也就是說此時從

fffffff0h

處取出的還是一條遠跳轉指令

jmp f000 : ***x

(我跟蹤除錯過好幾款

bios

,這裡的

***x

似乎都是

e05b

),問題隨之而來。這個遠跳轉指令是要更新

cs暫存器和它的

shadow register

的,也就是說執行這條

jmp f000 : e05b

之後(也就是

cpu執行第一條指令之後),

cs將被更新成

f000

,其實cs

原來就是這個值,這裡說不上是更新,但cs的

shadow register

就不一樣了,它被真正的更新了,它的

base

域被更新成

000f

0000h

了(高12不再具有觸發成

1的功能,那個功能只在機器啟動到第一次更新

cs的內容期間有效)。這個

base

再加上虛擬位址中的偏移量

e05b

,得到實體地址

000fe05bh

,這就是

cpu執行的第二條指令的位址,但是這條指令的位址已經是

1m以內了。但我們不要忘記,這時的

f000h

段內可不再是

bios rom

了,這一段此時安排的事實上是我們的

ram空間,這一段

ram需不需要初始化才能使用那還另說,關鍵是此時此刻這個地方不應該有可以執行的**才對啊?

cpu第二條指令就跳到這裡不是自尋死路嗎

? 似乎走進了死胡同,但我翻閱了很多資料,找到了一點線索。在很久以前出現過乙個叫著

chips & technoloqies

的公司,他設計出一組被稱著

neat

的晶元組,可以將記憶體高階的

bios rom

對映到1m

以內的ram空間裡 ,並且可以使這一段被對映的

ram空間具有與

rom類似的唯讀屬性。這個公司後來被

intel

收購。但後來這種對映似乎就成為了一種標準。由於這種對映關係我們有理由相信,機器啟動的時候,

4g的最後乙個

64k裡與

1m的最後乙個

64k 裡應該具有相同的東西, 所以即使從

fffffff0h

用一條jmp

跳到000fe05bh

,也仍然能夠找到正確的**去執行。 那麼

bios

接下來要幹一些什麼事呢?它有很多事情要做,我只舉幾件有代表性的,其中有兩件事是

dram

的初始化和

memory sizing

。按理說這個時候

cpu還處在實模式下,

bios

還沒有辦法去確定超過

1m的記憶體量。另外還有一件事就是**和資料拷貝,因為對映到

1m以內來的

bios rom

容量有限,事實上還有很大一部分沒有對映過來,以壓縮的形式存放在高階的

rom中了,

bios在1m

以內執行初始化時難免需要將高階的那些內容拷過來使用,這也是不容易做到的。但不要忘了,我們可以使用前面說的將段

break成4g

的方法來做成這幾件事。當然,似乎還存在著這樣一種可能性,那就是切換到保護模式,這些事情就都可以做了,並且好像沒有必要再切換回實模式。情況沒有想象中那麼簡單,從我前面的那個實驗看,我切換到保護模式之後只執行了幾行非常必要的將段

break成4g

的**,其他的事情一律不做,因為保護模式下有非常嚴格的特權檢查,並且需要設定

gdt,

idt,

ldt等一系列的**,一般的**是不容易在保護模式下跑起來的,所以想在保護模式下完成整個

bios

的初始化,工程過於浩大,幾乎等於寫一套小型的保護模式作業系統了(

freebios

可能就是這麼幹的)。

當然我也有足夠多的證據證明我們常用的

bios

都使用了這種

break limit

的技術,並且它們完成

break

後都是迅速切換回實模式 。

---------------------------------------------

參考了x86 cpu在段式管理下的位址形成機制以及bios初始化過程對這種機制的利用

陳英豪 中科院計算所

CPU加電後第一條指令

當我們按下電源開關時,電源就開始向主機板和其它裝置供電,此時電壓還不太穩定,主機板上的控制晶元組會向cpu發出並保持乙個reset 重置 訊號,讓 cpu內部自動恢復到初始狀態,但cpu在此刻不會馬上執行指令。當晶元組檢測到電源已經開始穩定供電了 當然從不穩定到穩定的過程只是一瞬間的事情 它便撤去r...

一條cpu指令執行過程

計算機每執行一條指令都可分為三個階段進行。即取指令 分析指令 執行指令。取指令的任務是 根據程式計數器pc中的值從程式儲存器讀出現行指令,送到指令暫存器。計算機執行程式的過程實際上就是逐條指令地重複上述操作過程,直至遇到停機指令可迴圈等待指令。一般計算機進行工作時,首先要通過外部裝置把程式和資料通過...

第一條部落格

第一條部落格 csdn的這個markdown看起來好高大上啊,但是看不懂啊.本部落格是記錄dsp相關數字電源部分的學習的,這是我的第一條csdn部落格,第一次接觸csdn是在初中的時候到現在大學畢業工作第一年已有十年有餘。大學四年在遊戲中虛度,大三下學期開始接觸開關電源,本身學校普通不能再普通的本科...