|
因為再深入我也不懂,所以就淺談吧~* P# Q4 N; [- S7 f, g7 F
有錯請指正~
# y- J/ x" Y; N
8 o/ }$ Y# y/ i, q) }話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
- w) }9 c( H+ o$ T7 l例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
) b) g# ^# i. I1 T- Y
" ?6 w: r% {7 {3 ?3 q" H8 X+ F0 n大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通2 I5 [ p/ O1 p- \" O7 y! l, X
常這個位置都是放BIOS,而這個位置通常是0』。
/ Z1 K, E; ]& F1 `! n) j \' d3 _1 M
, Y# T' _1 t$ G, ?那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯
W8 }2 G! l' H又有什麼關係?
4 [: F0 d- B% z7 N# B* J2 ^- V+ k/ [/ Q
我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
' F' E0 x: r( Z3 z6 k2 J: ^( 通常就是跳到bootload or BIOS )' i. ]* ^9 I8 l8 r( y
『9 v: P) h2 _- p% c* ], {* Z
b start" D5 n$ r [6 y( q
ldr pc, _undefined_instruction" A" _0 {0 ?1 d) t) ~4 ~
ldr pc, _software_interrupt
. o" P* Q! Q+ e3 S- Oldr pc, _prefetch_abort
0 a) V& t& W9 n+ T& U; m3 ~ldr pc, _data_abort: T0 D7 W& u" R: M6 p/ ^5 G2 {7 B
ldr pc, _not_used
$ y, ?) }9 N, Vldr pc, _irq9 ]: J. U9 ]2 Y) \
ldr pc, _fiq$ ]2 U5 u& i5 f: n4 g, o" W
』
3 ^% ^% z. X" J- a: ^! i: |! {+ b1 \' ]% N0 O7 s7 e
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
7 M9 ?7 S0 H/ z& v意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個
' c- D% ]; H# m指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第
1 e9 O) ~+ C [/ W0 r$ q' N三行到底是幹麼的。
# n9 r7 ? [/ s( X, k+ O; N4 [$ ?' r* }4 h1 [4 U' \8 H9 O
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將
& o3 O- l- U, J. [( ]_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過
1 v* Y! k* i0 Cprogram counter這個東西,一個正常的CPU就是靠program counter所指
5 ]1 J2 z M q5 q. ?' d4 C的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方
/ D7 \1 a4 i% Y5 M% X8 z) I執行。而且前面七八行都是做這件事情。很怪吧?!!!, c0 b5 n+ y( F" {9 A. a
7 j9 x" ?# g9 M5 T: ~! y到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到
; w3 _* `8 ]( ?5 Y0 D真正的開機程序。
7 f& v t* K" C8 [* F
" J8 ~+ _8 p' X v+ m# S4 E看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用
. z2 Z7 { G( i* x+ |; a* T" g的?其實答案就是『exception vector』。* l2 C( r) y2 z e6 Y0 a2 P
' e0 G4 R; { b/ i+ |- s
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會# d7 `+ y8 `7 l# i" S' t
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4/ ^5 p( n+ g+ g3 y* R8 c
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
4 {, b b( F3 x( T
% ]1 M; A( g. i5 N/ e! t! D到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
0 f: [( O+ z# {2 nJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理
: i2 r4 o/ s+ z8 c& |各種不同的exception。那....萬一這些vector被改掉了呢?
% o. K3 ?) z& ~" Z0 s9 ?例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
2 P1 Z; ?, e! d6 N8 O4 j8 E作。
) Z8 \1 W5 {% r
$ a7 U. C" p9 ]char *ptr = NULL;
: h8 Q+ Y- Q- U* R. R6 Bmemcpy( ptr, 0x0, 10 );
9 A, S/ u! X/ _5 [5 P* S9 O$ T, J$ v" W4 d5 y( M
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
% f' s5 v n& S; v; C1 Z8 Z! Lfault,並不會怎樣,OS還是照樣活著。why why why?" b: ~1 Z8 U. S. }" z6 p
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
8 ^ S8 }3 O5 J# Y! eMMU,一種是cpu有兩個exception vector存上的位址。' G( A- }: Z9 N2 }
) F6 }1 L$ k% a7 M5 hMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問 z8 m" w6 P" H4 j* \
題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常1 X) f6 ~; L" Y4 @ [0 X
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
. m5 s) ^. M6 E( T置。(32bit 最多只能定址4GB)
0 M3 ?9 r. R4 O( @- K) d% I# k$ J, D8 L
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可 J1 b) M' l# m2 t) \; ]( N
以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
3 l- g+ |6 E2 B N# @% ^vector。
" x# s" Z& i1 }1 ]: v6 b3 k
. S/ ~) @$ i! h; Fp.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
6 f; X' h4 b6 n8 K會比較有感覺。2 g0 ?0 O1 c9 k7 B$ f$ N, z
0 X8 F9 ?) t* L' v9 F# t
p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
; N0 {! u a" c. ]0 Y) H這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會
& `+ ]" y/ i8 X0 n# t" p再深入討論吧!!
. {0 d! w/ d9 }3 q3 B* O. r+ I" N2 ]
---
" |# s* G3 T$ q4 x0 j8 |0 M& z想知道答案的朋友趕快call in進來
& @- D" W: S g, l前五名我們有優惠
* w7 l( J* U) Z- I& D現在進一段廣告~ |
評分
-
查看全部評分
|