|
因為再深入我也不懂,所以就淺談吧~
$ V1 k( M3 L0 z" r0 v* P8 u( f有錯請指正~
8 U m: o, } K6 i5 C& `8 b: d
. N; x1 M( }; X/ r3 I話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
" W1 H) J- z _; [例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。. g" f: R3 S* s( ]5 z
! Q T: }) H D2 w: k' K大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通+ ^! v1 l3 D8 J- x+ M
常這個位置都是放BIOS,而這個位置通常是0』。
( Z6 y; i8 X& y9 Y4 P
0 y: `+ ], P- J) o& t那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯& p% F% {, r1 w0 L
又有什麼關係?% Z5 M( b' P; ?
. ^& D1 X2 t5 v4 d1 F% o
我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的! p6 ~0 A! }* R$ P. z2 I
( 通常就是跳到bootload or BIOS ), X k: Y8 d6 O- g# n
『
& }+ C- J8 A0 Y" _: j- Rb start
& y3 N/ z- X: N! _1 s9 C7 N7 i* oldr pc, _undefined_instruction
) B/ O% z9 O; k, v! ]ldr pc, _software_interrupt
3 v8 v$ z# n' _/ ildr pc, _prefetch_abort8 `0 i5 d, N5 C5 R. u' w% @6 z# G, x
ldr pc, _data_abort: {% L, m0 _! l; b8 y. Y
ldr pc, _not_used5 p1 {+ ]& A* N/ m2 R! G4 V
ldr pc, _irq# C, d7 Q; r& Z* U
ldr pc, _fiq8 A2 t3 `) m( l6 ~( B% s
』
& [ o8 T5 c: X! J9 d' \ p0 N/ G2 F4 i( X8 g8 R3 b
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
4 ~6 t$ [5 m1 ~. `: _意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個$ ~0 U# K) S* ?9 }5 u2 b6 g
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第# D. P# v+ }% X
三行到底是幹麼的。* D2 j2 T \. ]7 Q: p! P
$ U0 d# \, K8 o- H* R. a9 l
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將
6 r7 N+ j) b9 Y% x_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過
0 g! {1 T" n2 G) P, f% T9 mprogram counter這個東西,一個正常的CPU就是靠program counter所指5 Y7 Q) ~ h/ p# O* m# @4 A
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方8 H* E. D5 }8 A7 o4 W- g7 i
執行。而且前面七八行都是做這件事情。很怪吧?!!!1 C9 _! L' _6 q
; D z5 W( i. |" \1 a; b到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到
3 K/ y2 p" z- c. A) Y* w) _7 b' O" M真正的開機程序。
# c& z& n$ e! b# `5 k5 Z
6 J& f) M- G% V9 n+ G5 x看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用
+ q7 K. `1 J7 h+ y) g9 @, F的?其實答案就是『exception vector』。3 ~+ }8 J6 w9 f0 x; V
3 S' I2 P! e$ u8 H, M0 [什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會
8 _! y, ]- m N7 K來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x49 ^8 I9 d- w! o. J: v( Y
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
# G/ W3 }! E) V" |0 x* x
9 Z, E; t x: U: {8 w到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
9 d2 u6 i, E5 H2 D H zJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理
9 |3 k) D1 p- m3 L6 C8 N& l4 s各種不同的exception。那....萬一這些vector被改掉了呢?
: C: g3 k* h5 g/ b" m例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動/ T+ o8 u4 {1 o6 ~% T9 a- x4 G& P
作。
6 `# {6 N4 i1 @5 K# o n7 `: _5 n. N9 }
char *ptr = NULL;0 u3 j9 Y- O! k+ x5 m' P3 C
memcpy( ptr, 0x0, 10 );1 e! _7 L4 V5 | W* b) M
; L" b$ w' ]8 ?2 F5 w! ]% p那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
) A; r7 ~' F/ a+ {1 C# ^fault,並不會怎樣,OS還是照樣活著。why why why?
7 g k" J8 H) y9 g1 r- W! p: T. F原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
8 _/ R- ]+ \6 u2 IMMU,一種是cpu有兩個exception vector存上的位址。
9 c8 w; n) O/ v/ R S7 i) r
: z0 j8 `: P- m! L, jMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問( h$ V+ M% b L2 T9 m+ W8 n4 y- B0 X/ }
題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常
@+ s" c2 O: w, m是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
6 B+ R& H: i" O9 D' c置。(32bit 最多只能定址4GB)2 F3 M9 z" p6 t: y1 |, x6 F
: c) B L: x! x6 Y/ ?! G( q0 n
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
4 J7 c& B. V% y9 n! H8 z. R3 O以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
" Y6 C: M3 w& u; \; g5 R# Lvector。
8 w6 s, [8 v7 e1 K- R9 X+ P' d# `
, ]1 o: D- t7 [+ Q5 v8 cp.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,8 k4 ^# ]* {* N" m) C
會比較有感覺。' R' `" F/ ] U8 n, G
; |4 N6 D# d# Bp.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
/ G& S% w$ t$ O) k8 L" r# m0 M& K這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會
2 p5 P" }" ?" _& A7 ]7 d$ }& {' f! L再深入討論吧!!& K+ H- F6 u: A9 f' |! N6 ]3 w
& g( a, Z2 C+ X1 K% S; j5 W% U. ~% ~---% r: M& E* p2 l: q& {
想知道答案的朋友趕快call in進來7 q, z* t- J4 v; H
前五名我們有優惠& J, p6 D9 i( Q
現在進一段廣告~ |
評分
-
查看全部評分
|