|
因為再深入我也不懂,所以就淺談吧~6 a9 K, e: H: F1 |/ A- o
有錯請指正~
) E8 N) \6 H7 c" D+ H2 m( R! D% [( O
話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
' O( P" n" v2 O例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
4 H/ o& {3 H; i1 ^2 c
1 Y% S2 z8 G2 I. h; D( o大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通. P" N7 H$ f( p5 c
常這個位置都是放BIOS,而這個位置通常是0』。) f/ n4 ^1 F( [( `+ p9 Z
; L g$ U& x* V3 n4 E那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯. f6 [+ n- I- E# a, P& g
又有什麼關係?/ |+ o5 T( m1 B
9 U) b% w; x# J2 A, @) p+ ]
我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的" n: Y$ w" x' f& [; m4 E
( 通常就是跳到bootload or BIOS )
) \9 y9 [+ m( A5 ]4 H『
9 N6 c: r% X* f7 u3 Pb start
7 W( }3 U, G, L8 Z0 j1 v" R+ bldr pc, _undefined_instruction& K" y7 D: W% l0 j2 h( e! p$ [- H1 g
ldr pc, _software_interrupt0 \7 D" B3 Z1 I* L' t
ldr pc, _prefetch_abort
, o9 {& m# A" x" }+ zldr pc, _data_abort
% ^* S" M" a3 Dldr pc, _not_used6 [* u4 H2 i& B/ v1 H1 x
ldr pc, _irq
/ t" E" e% G4 v5 Jldr pc, _fiq' W% G+ N6 u9 v4 ]3 e
』
6 B4 b1 w9 L) y! S
' G( J- t2 b- R) `" z6 j上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
( S4 r$ D2 q3 |0 Y& R9 {$ M8 j意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個0 Y: `- g/ [- V7 {' }
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第
. q: \! H2 u \6 @6 i三行到底是幹麼的。2 e2 V( s* F+ ~8 a
7 v9 `# b. z4 U2 k! ?. y8 M
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將0 f" J: C5 ]+ }+ q
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過1 n D8 O E Z7 k9 K0 t
program counter這個東西,一個正常的CPU就是靠program counter所指5 @" w% H6 j o0 Q. z/ E
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方
5 T+ H7 t' U6 Q- P( m! ]執行。而且前面七八行都是做這件事情。很怪吧?!!! `) y! {4 Q" ~6 `
, x r* q3 Z; H% E到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到; X3 \0 x" M7 N1 l, p3 e" c8 ~
真正的開機程序。
# E7 m. `: Y9 `9 B& }$ ?" ], c8 U; Q, C' o- u/ X. `' @
看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用7 M% @6 n+ x3 ?9 }# [1 L2 m
的?其實答案就是『exception vector』。 a: e Z+ u* }' P ~3 ~
1 L9 W! ]" ^6 R7 e( ?- \什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會: k3 k: m4 a* ?1 R
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4
9 }( O; ^" n# {4 F+ g0 }位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。# X T- Y; P. o6 Y+ Y
* s+ ]2 O6 w9 P. `9 P. E到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
: b8 g( w' o3 S' G0 J* G( y! i PJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理
# K* S& {% j7 A1 M3 [各種不同的exception。那....萬一這些vector被改掉了呢?- c3 }& s4 B2 p% c
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
5 y2 C. A' {" i& |; g作。
( }0 g- z% s3 }8 Z) o- D$ ?! R
. ?& T% E; y4 i) a: t* e" bchar *ptr = NULL; _* s0 f- j: `0 e/ Y( _
memcpy( ptr, 0x0, 10 );
9 [8 n( i7 d( y, E* x; W( o( i+ b; U" D3 s' j5 s3 R# l
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
5 z; E% \5 S/ [3 O4 j( z% Mfault,並不會怎樣,OS還是照樣活著。why why why?4 p: R4 Z( P- e( ~
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
5 ~1 ^5 F. o# h: r5 _) k- H9 N2 ?MMU,一種是cpu有兩個exception vector存上的位址。0 N0 G( m8 r3 Q4 I# V% k" n9 M
G, ]" U- b( t* u; K1 I2 xMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
" i: [" O2 X; }) X- B題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常7 O+ P+ `* I: y& L
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
1 w! r) ^; C1 \' ?/ J+ v5 {8 w置。(32bit 最多只能定址4GB)$ z/ M2 d5 h* M3 o6 L
8 ]" u: g/ C6 i/ b# t5 w第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
1 K+ z' ]7 b+ F- L) {1 |以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception6 C7 r- E; ?2 C6 R
vector。
O0 f* ]7 D# e2 x4 j+ G0 C) J/ v& k$ F& S
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,& l, y; ^/ b+ x4 u
會比較有感覺。& c2 S3 j# U, ?$ l) `7 S1 a
]7 Q4 ]' `; n) f$ Np.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
( K8 {# Q% R& Y3 R- d3 @這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會) J, ~4 N) i) H6 F% D
再深入討論吧!!% g* c8 a F( @ N8 B
' l' g) R+ u* Z9 |2 [1 \---
/ r" C% j. O a) I4 G' r! V$ d+ Z想知道答案的朋友趕快call in進來
j# ^+ l- G, a$ i前五名我們有優惠0 I0 O6 ]: F% E" r7 T/ v
現在進一段廣告~ |
評分
-
查看全部評分
|