|
因為再深入我也不懂,所以就淺談吧~
# |7 ^) @; r r( C/ n; Y有錯請指正~
L: V' I4 k8 \+ A- Z a8 S' Z& L! G( r& S. d
話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
/ c+ {, _; w) j K例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。/ j5 Z9 N3 g3 D! z
, X" D$ J" M) o" Y& e$ [: G$ |
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通
: L- p4 J& U5 ^: X/ V常這個位置都是放BIOS,而這個位置通常是0』。
' i% h0 [: S+ d8 s
) q' T$ `; V% O; w5 z% s0 X6 ~那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯# V4 s1 k! n8 J5 }. a1 O
又有什麼關係?. [/ u$ t7 F4 ?2 P% N! w. O5 Y
3 D+ J) w+ z6 l" Q5 v% w9 T
我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
5 }0 x3 M* l3 C; E( 通常就是跳到bootload or BIOS )# U; I2 u1 [* ~$ _" V+ d# e, |% Z9 R5 v
『
3 G1 Q0 |& K, B+ L0 z8 N; Db start8 } Q8 o' [/ E4 b( n5 C( \9 h
ldr pc, _undefined_instruction) r. r; u6 y/ w2 b6 o: R F
ldr pc, _software_interrupt+ B0 B$ r! `* D+ J
ldr pc, _prefetch_abort8 w' Z) Z; y0 j
ldr pc, _data_abort' C' N0 K" `+ k7 n: {
ldr pc, _not_used
5 r3 t& x' t0 `# L4 s: }0 e$ ]9 bldr pc, _irq9 r b& G2 X: y5 r5 E
ldr pc, _fiq
# D" X' p; X: r9 c) A9 n』0 L& b" x# u2 l n2 @+ K0 T
+ ?+ |% s4 z* w8 |% \) c5 Q% b上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
8 n8 _7 a5 E* l! D4 G意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個8 f# ^# H( j/ ]. x9 }' P
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第; c' l1 g% K$ d# F: q- v) {9 W
三行到底是幹麼的。
5 Y. n( G0 E5 Y& v" F' [2 Y3 y# D! S6 Z0 G3 r0 u+ M$ v
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將8 w5 a9 h& A( I; Y
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過8 T# H- W; w+ W4 z4 A! m$ M
program counter這個東西,一個正常的CPU就是靠program counter所指5 M# i6 q% f. C/ w0 S1 k. O
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方3 S4 b: M3 Y8 O N( D; P Y: f" M$ X
執行。而且前面七八行都是做這件事情。很怪吧?!!!* T2 V! P; s4 \0 ~
! W5 m: }! G1 S, a1 K1 _到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到
! ]9 v u( o& t8 z9 W真正的開機程序。% p, c6 { e7 w$ r2 a4 w
! ^! Y" G: c8 A: c看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用* ^, |" @$ c$ G3 L( T: R( B
的?其實答案就是『exception vector』。: }: T) }2 b3 j+ I0 M
}. S1 L. Y: e G4 a7 r
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會
8 N) H) ?1 e" \( I來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4+ \- ?" G+ U8 d, g8 O
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
/ p+ V9 T. C9 _4 h; C
8 ]+ T- o+ L0 p. j1 P* r( D到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
2 b) E3 [* H( H; a/ @' JJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理
* T4 I" j5 e2 g1 B: o; H1 j各種不同的exception。那....萬一這些vector被改掉了呢?
d" c" f7 `6 t3 ~4 p, A2 L& @例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
' Y6 Y! j. S# m2 w作。# t1 m T8 G! m$ @- s$ ?
. x6 |# ~* o! S: o! @; d
char *ptr = NULL;
, y9 K4 \5 C/ _( Qmemcpy( ptr, 0x0, 10 );
- j* l( R2 l: T9 L2 q% b& G0 h% R% m% u7 c ~* _- b% s, ]* ~
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
: K% P0 w# O0 h/ R8 c7 [7 @fault,並不會怎樣,OS還是照樣活著。why why why?; L7 u& L! L+ B, M
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
; c- [0 u9 D! M3 D5 M6 q) Z. s1 LMMU,一種是cpu有兩個exception vector存上的位址。1 s* @/ r. v0 V b% a. X
- o$ r; r4 ]9 b+ n
MMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
; D( p3 D) l- N8 ` O& u8 L題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常
/ p* G" k0 C8 M* v& ?# K+ Y是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
6 i& |) y- v) z4 F' s/ F置。(32bit 最多只能定址4GB)+ k3 q; n6 G& N5 T B9 ~
" P0 f0 Q5 v4 l) R- X
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可3 Y0 `4 p/ X. B
以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
1 N/ _0 v( [3 C/ Z" q# {$ a4 A" wvector。. Z+ j) j; _ h+ t6 N" [
8 v4 }: n# ]$ y/ J) F7 Q4 I- k+ W- tp.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,; k5 Z- m1 Q- p# k$ o3 ?# g$ B% q
會比較有感覺。
7 s5 }* A& i" c
! m! T" K, t H" Ep.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
' [$ u! l8 y9 f% b4 d. x% g這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會9 Y9 P5 E/ O9 A! d% D
再深入討論吧!!
+ O9 ^. i6 G, ^( X( b. Q' \+ l
3 N8 x( e; p j f---5 i! [$ P! W" P' i
想知道答案的朋友趕快call in進來7 W3 Z6 l: N5 X( G3 e a
前五名我們有優惠: X' C5 y2 Y, z; J
現在進一段廣告~ |
評分
-
查看全部評分
|