討論區快速選單
知識庫快速選單
網路投保旅行平安險 政府補助!學嵌入式+物聯網 傑米的攝影旅遊筆記
[ 回上頁 ] [ 討論區發言規則 ]
CPU第一條指令的問題~~~
更改我的閱讀文章字型大小
作者 : harrison(harrison) 貼文超過200則人氣指數超過30000點
[ 貼文 232 | 人氣 43332 | 評價 330 | 評價/貼文 1.42 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/8 下午 01:58:11
我最近在看P廠商的BIOS的一些BIOS結構,想說去從FFFF_FFF0的位址開始追,所以用工具去記憶體FFFFFFF0 看到了下面的資訊:

FFFFFFF0: E9 D3 E9 00 00 00 FE FF EA 39 EA ......

我之前有看過IA32 software guide 裡面說當Power On之後,CPU會去FFFFFFF0的位址抓取第一條指令,而這個指令是存在於ROM之中(CPU Reset 狀態==> CS=F000 , Base Addr=0xFFFF0000 , EIP=0000FFF0)

所以第一條指令的位址是BaseAddr+EIP=FFFFFFF0 (指到4G那邊)
而BIOS文件總是這樣教我們說,第一條指令必須是Far jmp ,所以我就想說執行完Far Jmp之後BaseAddr會被更新成000F0000,所以接下來CPU就會1M那邊執行第二條之後的指令( BaseAddr+ EIP= 000F0000+EIP 是指到1M那邊)

所以我有3個問題 :
1. 第一個問題是我在MASM產生的BootBlock.MAP檔案中看到 Program entry point at 0000:D8C3
    而0000:D8C3所對應的指令是不是說當整個BIOS ROM產生之後會放在FFFF_FFF0的第一條指令?
    因為entry point 只做了一個JMP 指令到某個位址 (E9 xxxx)...

2.我實際上看到的第一條指令是E9 (Jmp)而不是EA (Far Jmp),所以是不是代表說CPU執行完第一條指令之後CPU還是工作在4G那邊的位址,直到BootBlock之中做了Far Jmp才會指向到1M那邊的 BIOS位址?

因為我上次查的資料是告訴我要做Far Jmp 才會改變BaseAddr (因為已經不用CS暫存器定址,而是使用64 bit隱含位址暫存器,我是參考BigReal Mode與IA32 software guide 的說明...)

3. 最後一個問題是,第一條指令是E9 D3 E9 理論上應該是Jmp E9D3 ,為什麼我用工具反組譯後看到它是Jmp E9C6 而我在.MAP裡面找E9D3 找不到有對應的程式,但是找E9C6就是對應到BootBlock的實際開始處理的進入點程式, 所以想請問前輩為什麼我看到的是E9 D3 E9 但他卻不是Jmp E9D3而是Jmp E9C6 呢???


作者 : armour(Armour)
[ 貼文 6 | 人氣 7 | 評價 0 | 評價/貼文 0 | 送出評價 2 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/12 下午 02:46:28
3. jmp(E9)後面接的operand是相對位置,把現在的IP(*)加上operand就是target的IP。
    0xFFF3 + 0xE9D3 = 0xE9C6(扣掉進位1)
    (*當這到指令被CPU抓取時,IP就變成下一個指令的IP=0xFFF3)

1. 純猜測:P家的BIOS可能有其他程式(不屬於MASM)去把第一道指令直接填到Binary檔裡。妳可以打開makefile看看裡面有沒有這樣的資訊。

2. Intel的BIOS Spec.是建議第一道指令是Far Jmp,不代表一定要這樣做。妳可以trace BIOS code,看他什麼時候做Far Jmp或是用什麼方式切換到real mode。
作者 : harrison(harrison) 貼文超過200則人氣指數超過30000點
[ 貼文 232 | 人氣 43332 | 評價 330 | 評價/貼文 1.42 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/13 下午 02:28:46
嗯嗯,我了解了,感謝前輩回答!

另外我還有個問題可能要有懂P廠商BIOS的前輩來幫我回答了:
P廠商的BIOS在做Transition from Boot Block to the System BIOS的那段code裡面他最後跳躍到SystemBIOS的位址,這個位址怎麼跟我在F000:E05B 裡面看到的位址不一樣???

F000:E05B E9C775 JMP 5625
Offset 5625是BIOS Entry Point 開始的地方,即POST測試

但是我追到的Code那邊是做了一個Far jmp 後把控制權轉給SystemBIOS(他把位址放在某個Struct欄位,我有小修改Code 以避免版權問題...),其範例如下:
宣告部份:
     AddressFar DD ?
我追到的Code部分:
     jmp DWORD PTR gs:[di].Structure.AddressFar

理論上這段Code應該也是要跳到跟F000:E05B同一個地方(F000:5625,BIOS Entry Point),但是我去看記憶體的內容這個欄位的內容是25 56 0F E7 -->變成跳到E70F:5625 ???

這到底發生了什麼事情???為什麼會變成這樣???
作者 : kib72377(史努比) Visual Basic卓越專家Assembly優秀好手Access頂尖高手貼文超過1000則
[ 貼文 1454 | 人氣 1891 | 評價 8600 | 評價/貼文 5.91 | 送出評價 31 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/13 下午 05:22:43

應該是跳到保護模式了.
前面那個結構應該就是 區段的描述器結構.

看bios不能再用 real mode方式去看,
因為從286開始,bios就已經有進出保護模式了.
作者 : harrison(harrison) 貼文超過200則人氣指數超過30000點
[ 貼文 232 | 人氣 43332 | 評價 330 | 評價/貼文 1.42 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/13 下午 07:23:14
感謝前輩回答,可能我沒有表達很清楚,我再多描述一下我的問題:

P Code 放了一個Structure在0xFFFE8EC4(不見得每個BIOS位址都一樣),而這個Sturcture的第一個欄位稱之為BIOS_SIG==>D2 86 86 D2,在這個Structure的其他欄位中的某一項欄位是他用來進入System BIOS的位址,也就是我前面所描述的Code,而我利用Tools在Windows XP底下去找到這個Structure然後看那個位址是Jump 到哪去,所以才發現他的位址怎麼跟F000:E05B 所Jump的位址不一樣??? 理論上他們是Jump 到同一個地方(POST Entry)但是為什麼我看到的位址不一樣??? 是不是我找錯地方了???

另外,BIOS並不會進入保護模式工作,只會在設定BigReal Mode時短暫進入保護模式,而且描述符是在切進去保護模式設定給Flat Memory Mode,之後就不會再被使用了,設定完Flat Memory Mode之後,BIOS會再切回去RealMode (此時應該叫做BigReal Mode),所以這邊的Structure並不是那個描述符...而是"bios Entry Structure"...

作者 : seanchang(H) Assembly卓越專家貼文超過1000則
[ 貼文 1200 | 人氣 773 | 評價 3240 | 評價/貼文 2.7 | 送出評價 43 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/3/26 上午 11:12:51
>3. 最後一個問題是,第一條指令是E9 D3 E9 理論上應該是Jmp E9D3 ,為什麼我用工具反組譯後看到它是Jmp E9C6 而我在.MAP裡面找E9D3 找不到有對應的程式,但是找E9C6就是對應到BootBlock的實際開始處理的進入點程式, 所以想請問前輩為什麼我看到的是E9 D3 E9 但他卻不是Jmp E9D3而是Jmp E9C6 呢???
>
沒有看過P code. 不過我可以解答你 map 的問題. MAP 只能看到 宣告為 public的 label(processure or value). 所以map不是找問題的萬靈丹.
作者 : andychen63(Stardust)
[ 貼文 4 | 人氣 5 | 評價 0 | 評價/貼文 0 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/16 下午 08:07:59
你執行 Debug.exe
然後做下面動做
;因為 BIOS 是 FFF0 開始執行
a FFF0
db E9 D3 E9
然後按 Enter 2次
再來
U FFF0
你就會看到答案囉.

作者 : andychen63(Stardust)
[ 貼文 4 | 人氣 5 | 評價 0 | 評價/貼文 0 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/16 下午 08:10:04
你執行 Debug.exe
然後做下面動做
;因為 BIOS 是 FFF0 開始執行
a FFF0
db E9 D3 E9
然後按 Enter 2次
再來
U FFF0
你就會看到答案囉.

E9 D3 E9 不是跳到 E9D3, 而是以現在位置往下跳 E9D3 位置, 近端跳耀超過 FFFF 會在從 0000開始算
作者 : andychen63(Stardust)
[ 貼文 4 | 人氣 5 | 評價 0 | 評價/貼文 0 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/16 下午 09:06:16
Seg : F000
FFF0 E9 D3 E9
執行後 IP : FFF3

FFF3 + E9D3 = 1E9C6

Seg 不變
所以跳到 F000:E9C6
作者 : harrison(harrison) 貼文超過200則人氣指數超過30000點
[ 貼文 232 | 人氣 43332 | 評價 330 | 評價/貼文 1.42 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/30 上午 10:18:58
我有整理了一些資料在我的部落格,底下是我整理的部份,給大家參考!
如果有誤請前輩指正~謝謝!

x86 Intel CPU 的第一條指令~~~

一般CPU reset 後, 會預設跳躍至 0xffff_fff0 位址去執行, 這個位址是現行 BIOS ROM 映射的位址。而CPU被重置後的暫存器值為:

CS= F000h
EIP = 0000_FFF0h
Base Address= FFFF_0000h (隱含暫存器,不可見)

由於IA32 手冊中說明,IA32 CPU定址方式是利用Base Address+EIP,所以第一條指令讀取的位址是: Base Addr+EIP=FFFF_FFF0h,至於為什麼不是CS:IP的定址方式,則請參考IA32 手冊說明。

一般的做法是把 bootblock 的source code 放在這個區塊, 但是並不表示這個位址的 code 一定是 bootblock. 簡單說就是BIOS要不要做這一部分的功能就由你或是BIOS供應商決定.

一般而言,若有包 bootblock,則先跑 bootblock ; 之後才跳到 BIOS entry point ; 若沒包則直接跳到 BIOS entry point ( 這邊說的BIOS entry point 就是POST code一開始的地方,而他的第一條指令都是 cli ,而他的位址是固定的,也就是F000:E05B) !

Power on時 CPU 第一個 code read 一定是 0xFFFF_FFF0 ; 在那邊有放一個 jmp 指令 (因為 FFFFFFF0~FFFFFFFFh 只有 16-byte空間,無法放很多 code),如某個BIOS 在那個0xFFFF_FFF0的data 如下所示:

FFFFFFF0: E9 D3 E9 00 00 00 FE FF EA 39 EA ......

CPU讀取到E9 D3 E9 然後依照這個指令的描述 "轉跳" 到其他的地方 ,其中E9 是跳躍指令,jmp(E9)後面接的operand是相對位置,所以E9 "跳躍的位址"的計算方式:

"把現在的IP(*)加上operand就是target的IP "

0xFFF3 + 0xE9D3 = 0xE9C6(扣掉進位1,因為64k limit,範圍0000~FFFFh,會裁掉超出的部份)
(*當這到指令被CPU抓取時,IP就變成下一個指令的,所以目前的IP=0xFFF3);

若這 "跳躍的位址" 地方放的是 bootblock code,則先跑 bootblock。
所以由上面的範例可以知道,CPU讀取到第一行指令後會Jmp E9C6。
如果你是使用P廠商的BIOS,那麼這個位址就是指向BooBlock區塊的Entry point,因此可以證明他是有包BootBlock。

另外假設你的BIOS ROM大小為1MB ,那麼他會被映射到4G~(4G-1M)跟1M~640K的某幾個64K 的區域,簡單說就是4G~4G-1M 剛好就是對應到整顆BIOS ROM,而1M~640K則是某幾個64K會對應到BIOS ROM,例如E000h Segment(64K)或是F000h Segment(64k)=BIOS Data area,至於是誰要被映射過去就要看北橋的暫存器內的設定。

[註] 此篇文章整理自己在程式設計俱樂部的討論結果整理,感謝一些前輩指導。
[註] 如果要查看BIOS ROM的內容方式有下列幾種方式可以參考:
1.利用Debug dump 方式:利用OS自帶的Debug工具去將BIOS ROM資料讀到某個空閒的記憶體內查看
a. 在C:\> 鍵入 debug xxx.rom (以 256KB(3FFFFh)大小的BIOS ROM為例)
b. 在Debug提示"-"下鍵入"L 4000:0",其中L為Load意思,載入xxx.rom到記憶體4000:0的地方
所以40000~7FFFFh處為 xxx.rom的所有內容
c. 在Debug提示"-"下鍵入"D 7000:FFF0",其中D意思為Dump (查看記憶體資料)
此時會出現 7000:FFF0處的記憶體資料(也就是你載入的BIOS ROM資料)
2.若BIOS ROM size > 256KB,則使用 ultraedit 來看 ROM內容
3. 還可以使用反組譯工具Win32Dasm 或是IDA pro...等工具查看。
 板主 : 徵求中
 > 組合語言 - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - 組合語言 - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
組合語言
1 H 2220 
2 liaoo 990 
3 青衫 970 
4 牧童哥 940 
5 史努比 920 
6 qq 480 
7 GHOST-JACKY 330 
8 ]CALL-151 310 
9 harrison 300 
10 掌握文武半邊天 280 
組合語言
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2017 程式設計俱樂部 http://www.programmer-club.com.tw/
0.078125