|
因為再深入我也不懂,所以就淺談吧~. Y9 c( Z* I4 J2 o, v: g
有錯請指正~
6 }9 X3 F4 @9 i( t0 Q( j3 Z$ g/ C
- `1 A. n! G1 _: {* J" F話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。# \$ M e) f3 `+ O7 ]
例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
6 z, F: z$ _/ j9 @: y% o7 D. v$ E1 m0 A$ Y) c/ V
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通' l7 H) f9 d ]/ q4 i
常這個位置都是放BIOS,而這個位置通常是0』。
7 ]( z/ u6 v/ A8 Q( @8 y5 t
0 q/ U/ e& h0 A1 f7 M9 f3 V那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯
y Y6 A. u$ Z' E" d# }4 [又有什麼關係?
2 |6 K" e; Y9 Y" n/ g
2 r8 B7 Q3 v1 H我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的1 ?) d; O; i0 R+ G
( 通常就是跳到bootload or BIOS )
( Z4 J+ z; L& s: Q( }7 u* t『
* ?( i, _& {/ X3 X, gb start
8 K' ]% b6 y2 X/ b. cldr pc, _undefined_instruction2 e) u0 x+ l" `- i9 F% M
ldr pc, _software_interrupt
; V0 S: K' s* o* K& rldr pc, _prefetch_abort
6 N) l+ p3 U1 o% O3 Oldr pc, _data_abort
+ @ d* e* a' p1 m- j3 @ldr pc, _not_used9 p' T( ?+ ~5 ?* i( Q* Q
ldr pc, _irq# u |" ^$ ~& C9 r
ldr pc, _fiq
# D& n4 S, h/ ^- P6 G』% Q6 W; o. g5 ^2 _* t
& |" A7 P* q- A, ^上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的& H: V% {5 j4 x2 g' h5 p
意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個
& w, n( N: e+ G) h指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第0 \, S6 Y. m) z: J. }. I
三行到底是幹麼的。1 U4 h, D* G7 w; z h. Z( {0 L
2 K/ Y: {3 V; J( D9 u我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將- O0 J! F3 z7 \$ x9 }
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過
q1 `% g6 K3 Sprogram counter這個東西,一個正常的CPU就是靠program counter所指8 |; T% {. L8 j6 T! x0 \
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方
! g. i+ a' s- N執行。而且前面七八行都是做這件事情。很怪吧?!!!, L2 j% H; x/ Y2 S# K6 X0 p
' h5 }" g* ?$ q" j( I6 i0 `
到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到. t3 P& `8 C7 K1 N% o. W
真正的開機程序。
% `- w7 K4 c- p! \0 {5 q7 B+ p1 Y+ C6 { D
看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用2 u" V/ f, t7 z+ l1 u6 P
的?其實答案就是『exception vector』。
7 l& u% ^2 @4 C: @' M' y* _, R% p2 {
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會1 D0 Z) v0 C/ u( L% O, d
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4
! y# @0 U K- Q, N2 S0 @位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。7 j! A! @8 w8 E7 j
; p: c) P# {) e$ _
到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再% P8 _3 [6 o) P6 Q& b1 K
Jump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理) T( c2 b, z) a& B6 c! Y9 [
各種不同的exception。那....萬一這些vector被改掉了呢?4 h2 }5 F" n0 }. {6 G, p, J
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
4 U e t2 ?7 u4 F& h' p& V作。
. L& R$ C* o. C* w6 Z; z# b5 X0 ~
char *ptr = NULL;" e8 ~2 P, Q# i A1 O
memcpy( ptr, 0x0, 10 );4 e6 N# Z/ Q3 x8 }! ]6 a
7 s. A5 f" h1 \7 E那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
, V8 r. N) n! d6 p0 w% ffault,並不會怎樣,OS還是照樣活著。why why why?
9 f& ~4 n7 T4 W+ e! b原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是5 S3 J' j7 w8 ^3 J2 l! `
MMU,一種是cpu有兩個exception vector存上的位址。
7 w" B. j) @7 A4 b
. K7 T4 C2 I# E KMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
0 e0 N* H1 c+ j- \1 F3 v! I+ x題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常
, Q0 E0 K, \' R" t) O, N! x& p是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
1 M1 D) q# P; ^( ?+ f/ s4 N, d置。(32bit 最多只能定址4GB)/ ~- D' u& L8 c* K7 t
& n- }. |, X" j7 r4 W
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
C! u! a3 D7 m) Q2 S以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception% ~& u! U8 J9 d; h4 X
vector。
. q' t. B/ H: ^0 }3 \ M l8 `) b) S/ a0 ]* a: i
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
* G' q ~* Y: V會比較有感覺。' r! y# Z+ ]5 {! {; E( W8 |' R; S7 Q
; V. i& ^+ U7 j! B {
p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
' u1 U2 R( q- k0 }1 ^這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會
( }9 Y( B/ o) m* @7 K: v8 R7 e再深入討論吧!!3 R7 o; w- g n5 J& _0 O& D" n
) _! Y% n' I: @2 R( s: R2 t ?--- G- V) k! i/ F
想知道答案的朋友趕快call in進來/ q! n; P7 o1 b/ i; u. K# D! D0 B
前五名我們有優惠
- w" K1 {3 f7 c6 ~6 B+ h$ u現在進一段廣告~ |
評分
-
查看全部評分
|