|
因為再深入我也不懂,所以就淺談吧~
3 `9 O: t. {) o7 o" S. \有錯請指正~
' _% F, z; b" k7 z6 @& N3 L3 a0 {5 d* M9 c1 h8 [, V
話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
) m, y5 _. v- K9 H1 p: R) s' @例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。4 s. }' R- b0 ]; B% ~; Q$ c) e& _& @ c
2 d. W. ^. h' ^1 \% m* i
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通$ k( Q$ o2 n: d+ z8 \; U
常這個位置都是放BIOS,而這個位置通常是0』。% ^% `- B( z4 P9 C
- V `4 R: v( q# b' I3 t那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯
0 w- I" z+ ^+ t5 L又有什麼關係?
& h3 K, R: C; D/ Y. _* N& f) Y
& S2 E6 j" E1 E; ]我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
* W0 b# }0 S: P3 H* d( 通常就是跳到bootload or BIOS )0 c% A- A$ J# u
『
; D) r7 |. G9 u( db start
L% l3 k) h V. W5 Q% }ldr pc, _undefined_instruction+ G& e( ~1 x- l8 v2 z; R5 V
ldr pc, _software_interrupt% F6 y' E; b( R3 E3 q1 o1 @
ldr pc, _prefetch_abort9 w% } k: q# |& `- R" }" {/ K
ldr pc, _data_abort" F, K+ s) `0 t! ?" v$ ^
ldr pc, _not_used" E2 M! c, ]! I. j1 `! p
ldr pc, _irq
5 T3 j9 H' {. c$ I6 P8 P7 \ldr pc, _fiq
% u7 s/ z1 v. z$ D+ b& I" Y2 l』
- z. e g" Z* W) k( R: Z! u$ w* z P
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
T- i( V4 D! [3 g' y意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個
7 N4 Z* E0 n0 I U7 I, g指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第$ k1 i) P$ g" ]% G$ p/ [; A0 w) G
三行到底是幹麼的。, E K' T2 k# d+ [
. p: |- F. t7 E7 |. n我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將' w' |) \$ p3 ]# q9 r9 c L" A# i2 o
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過& Z! j; I! w, C1 C
program counter這個東西,一個正常的CPU就是靠program counter所指
6 \7 ]) h6 c6 \ h* e9 N的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方
2 q1 @5 r1 }. }# y執行。而且前面七八行都是做這件事情。很怪吧?!!!7 o3 N' _$ D" {9 a5 @1 p. Q7 }
K/ x% ?9 f8 m/ D: Y' B9 Y8 d, R到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到1 ?9 X* |$ i9 F3 [
真正的開機程序。
& B( \8 p' V* P6 }
) e/ d4 `( ~' N B6 Q( B看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用
1 h8 [2 o2 X) L3 m2 e4 _. H的?其實答案就是『exception vector』。
( W& G+ l' e7 m, j8 m1 d& M* c H* N+ S7 n
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會
( y; ]0 W. N' E* [2 ^- O來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x41 X4 R+ X1 I' Y
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。3 J; z- X4 n) ^; B6 n/ t
* }+ X2 Y9 |& I( F+ \- Z& {/ s* R5 K
到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
, b( C" _6 Y5 V8 Y) H; X( `Jump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理 l0 E8 A7 C0 ~9 ]3 ~
各種不同的exception。那....萬一這些vector被改掉了呢?
2 j8 H+ ^$ d3 h' ?: `" M例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動. d4 s. h3 k: E! Q5 L4 A
作。' B7 r/ l" d4 u
: k1 @0 \6 R, O; M
char *ptr = NULL;$ B" C; p& a2 P8 W
memcpy( ptr, 0x0, 10 );
6 |: D# D3 d6 S- x5 G3 j+ a+ h/ K- @8 H& f' y# D
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation) {% W2 {/ b" w& L
fault,並不會怎樣,OS還是照樣活著。why why why?1 `0 q+ n9 n3 a4 a; G& t( f
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是$ [4 |% @% q. x1 y
MMU,一種是cpu有兩個exception vector存上的位址。
( W W0 C+ i/ U' s" |- k# @( ]0 x1 [
o: E3 m5 u; ^5 h3 t9 mMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問- \5 g: e: T# p; m f. B& I
題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常
* |& k, `# S% D5 |: G C7 h) Z* |是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位, d8 C) `4 p! i3 _4 Q3 A
置。(32bit 最多只能定址4GB)
* y7 |: d1 `9 @, f
; Z/ |' @; u* i0 G9 A- m" v第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
, L ~& R/ P0 y* \; p$ X* }以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
" P! w* r- P( |/ |/ Avector。
) ?( b& w$ y- @
6 }* Y% S, w. O$ j8 Ap.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,: O/ U* _5 b" t% ~
會比較有感覺。6 W( [$ O9 s& R. O# ~
- L9 I2 u2 i6 e v- q! ]
p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
- s9 W6 P# R# ~ D這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會9 q4 m2 |" N& B
再深入討論吧!!
: | C9 P! ]! g2 a3 N! v
8 ]$ D) K% L& G6 d9 p, Y---& S9 r' Y, V& G9 I
想知道答案的朋友趕快call in進來
, Z, t7 V, v# t6 X6 o' ~2 ]前五名我們有優惠
: _2 E0 ~: D- M7 a, j) t2 K現在進一段廣告~ |
評分
-
查看全部評分
|