|
因為再深入我也不懂,所以就淺談吧~
! r$ [0 c0 j1 V9 p2 \& D! e6 I有錯請指正~
4 {. o& d8 k+ _& ^
5 \+ N. W3 Q. Y: c0 X+ W話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。* }8 {( y! M8 g# X
例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
6 U3 v, Y ]8 R& n7 d# u( U
: ?% M7 g) _: E7 w4 @大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通
7 Q z5 h- A, e7 y1 ?4 F1 s常這個位置都是放BIOS,而這個位置通常是0』。" [! X7 x& B! y7 W2 N$ ~9 ^$ e% x
+ O' ^. a3 D/ ?那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯* N9 {" m1 z0 w% k* K
又有什麼關係?, y/ ]+ m0 V; @& l
3 B) S9 n+ u- \1 h# e" {我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
, d: H' A [$ s% `- _4 u( 通常就是跳到bootload or BIOS )/ p$ ?) [ l( I1 G; l
『 G3 L8 w5 {. [. \9 J# _+ I
b start2 K3 P d3 O& h9 h; o) N
ldr pc, _undefined_instruction
u! M' l0 { y) ]+ P ]ldr pc, _software_interrupt* m1 I! R# R [7 O' F
ldr pc, _prefetch_abort
; s) F {7 T( h- e7 k' t& B4 Eldr pc, _data_abort: a5 t) e8 k* E9 U6 t. h
ldr pc, _not_used l. x9 \( }6 R/ U. P: _
ldr pc, _irq) l( Z$ g9 G$ N) J* F4 h4 d5 I
ldr pc, _fiq
0 f' E' L% S0 q: y』- Z# w2 L. y1 @- w: l+ B! n
G* }9 Q H5 p0 f7 {上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
) S+ M2 Z; W% W+ l8 l/ w$ P意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個# n( y) z$ k" p
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第& N- h$ h, c2 O5 K% X& H" ~
三行到底是幹麼的。
2 i. a( W, l( n+ B P" k
# r: m& J6 T1 S8 Q' P1 n我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將6 k- A- ?+ P; i4 g% ?+ |
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過& i+ \& N+ ^( z+ P( p# y a$ G
program counter這個東西,一個正常的CPU就是靠program counter所指1 f0 j" X+ D; n, q: y/ T! D3 m. d: X& ^
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方( G w1 V3 U: k. M) }. b
執行。而且前面七八行都是做這件事情。很怪吧?!!!
$ L; _! y0 K( C$ P/ z- N; d4 b6 E) ?& i& n
到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到
0 `: H) k6 x- p1 Q- b, N- n7 o' ~真正的開機程序。
! ]$ k$ Q7 V4 j3 o
0 R) o0 J% L: U3 Q" Q9 E看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用" i1 g& f$ L/ Z% k; Z8 w9 e
的?其實答案就是『exception vector』。: f! Q r6 E4 G6 ]- D/ H8 i
* \: n/ L. x/ Z* ]
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會: f! f$ j6 I6 u- h& i! C7 }
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4
" f$ s0 C. r# c1 c" a9 g位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
1 f( t+ \$ J2 p! U' v7 n# B& U/ Q) ?2 B+ U! {
到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再+ o* _( Y j7 }2 N$ S# m) r
Jump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理; C K+ T6 H" I! |9 B4 Y
各種不同的exception。那....萬一這些vector被改掉了呢?# {. G" B! V* H+ f6 U! E1 V! o
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動4 B8 N6 K1 y4 [- f2 |/ H
作。
2 @2 M4 e3 r! a3 ]' }7 Z( u" l
char *ptr = NULL;
+ @' Y0 ?+ E, E0 p% C& Ymemcpy( ptr, 0x0, 10 );
3 g/ S2 H+ X1 E5 f+ v, s- d( y3 ]7 N4 \3 _
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
( `, j4 O6 N7 r2 h& Dfault,並不會怎樣,OS還是照樣活著。why why why?$ P5 s; M$ k4 g+ Y5 x p
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
3 r8 N2 Y3 Q5 M3 @8 bMMU,一種是cpu有兩個exception vector存上的位址。
8 _5 Y: Y. m7 O0 i
( D$ z. F9 U0 u6 x9 @" `MMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問' n$ A u. y7 e& G
題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常
F4 o7 V% v @. D/ v# K是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
% h5 r/ h0 i% W }8 A; t, q( c置。(32bit 最多只能定址4GB)' y% M5 Z" I" i* B
1 _1 S: ?4 K9 K9 X3 L第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可5 n0 z/ ?3 p1 ^$ k5 q+ y
以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
7 I& D0 Q+ n' W3 Evector。9 |8 r0 k- n( R7 [+ I" r
- B- i) F; s6 C
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
- w" j# E+ F' I, O$ d- q會比較有感覺。$ D- t, B) M' H/ h" {5 x
/ s( h# A3 {% T. s7 i8 ?3 H2 H
p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
6 i7 y1 x1 L* q/ q這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會
: G7 I9 L, ?* a3 j! h再深入討論吧!!' _1 F3 N x( k
# ~5 h A; q8 J, F' L
---2 l: U% @7 Y: g$ ~& d. R9 o
想知道答案的朋友趕快call in進來% M- f# E% C' T' W# i0 O/ x# @
前五名我們有優惠' f$ D8 ^$ D& H0 n0 n' G
現在進一段廣告~ |
評分
-
查看全部評分
|