|
因為再深入我也不懂,所以就淺談吧~
9 D! t3 b7 c$ p# [. Y有錯請指正~6 j8 N2 [& _# h8 A- F; o# e0 q
% `) D6 Y! W; E3 t話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。, i+ e- Q/ g2 O$ `1 ?
例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
8 q* B4 y& m M6 W* S" L$ e3 Q, N) ]/ M8 F0 T
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通* [3 O4 h2 a9 w @: a: o1 c4 r
常這個位置都是放BIOS,而這個位置通常是0』。
9 k5 R. w/ u i) N, c6 V) Q2 O( z8 E9 z) d2 ?5 \5 W' m* V
那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯8 \/ Q8 _: T# h: _6 Z1 g) j
又有什麼關係?
4 Q% K0 C. E7 t/ p. j! e* F: w4 t6 A9 p' l
我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
! V: m! g" F _3 ]. J: `( 通常就是跳到bootload or BIOS )
: ~' N/ U' S3 n3 @, e$ I『) v0 Y& _. ]: H. J0 @
b start
, X2 @! _& V* m3 s" B3 m. `ldr pc, _undefined_instruction
- R3 U# n* z2 O1 T' X8 y% Qldr pc, _software_interrupt4 p; ?. E1 D. s
ldr pc, _prefetch_abort. O2 s `+ D; P$ l. Z* s" u
ldr pc, _data_abort9 x% ?, M& H/ i6 A2 c5 n( c$ d, c
ldr pc, _not_used
; n! b3 v! {7 ?ldr pc, _irq
) @# g3 I7 e, Sldr pc, _fiq( ^1 {1 w8 N y& ?
』
% \5 n, J+ \. o- q, R% u) v
: h% |: n- x2 ^上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的
6 E+ A3 B- @6 L- X' A" K, {意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個! c, m' B7 m) V/ V& |
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第, L# L" K) t( \3 O% `% O
三行到底是幹麼的。& O% G5 K* W0 G8 T
* o% G) `' T3 q3 U- l" H我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將0 g% P4 A8 u l7 k3 L" M6 @2 H8 y
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過8 V# E! v3 q1 Q2 U* Y
program counter這個東西,一個正常的CPU就是靠program counter所指
7 ]- C& \* t1 K/ W9 Z1 M! R的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方; J1 ^; S8 n* P6 ]
執行。而且前面七八行都是做這件事情。很怪吧?!!!! M5 D7 s4 V; \" n& h
# U* P8 G4 L* ]$ g$ A% w到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到* z/ \6 e' w" z$ Z8 [* s
真正的開機程序。
6 i, J% ~* r6 W; u+ F6 g4 w
0 ^* A$ ~+ L+ M看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用. o8 @% s2 V. |/ P
的?其實答案就是『exception vector』。: x i! k e1 _; U6 d
8 L% T D* i/ I/ _$ p3 C# i
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會
; G. t; x3 v' K+ A% l; p來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x46 B$ C# V- f8 @, W2 R
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
* N! }2 I6 r5 G, z, |+ A/ [3 N
! [& q# W; Q% t到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
7 @& b5 R! r& CJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理. v$ }9 x0 |7 s0 {9 c' S
各種不同的exception。那....萬一這些vector被改掉了呢?
3 b* R" p- f0 D3 ]例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
! U9 U/ |" E6 e. v U作。
% K) o2 j m2 l# g- n3 Z2 x+ m3 N" I# C9 w4 b9 y
char *ptr = NULL;
& K h& _& Y) \7 b wmemcpy( ptr, 0x0, 10 );& }" h( A( Z/ m( \* A* c
3 @" `. F1 t, w. j c- [9 \
那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
O- z6 g; z( U! efault,並不會怎樣,OS還是照樣活著。why why why? v6 Z4 s9 g7 L, a* F' Q6 H7 u! i/ ]
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是2 U" I* d. f3 @% O
MMU,一種是cpu有兩個exception vector存上的位址。
: N: s' I; V I% r3 p8 {1 F
. ~6 T3 {1 L( i; Q: }: zMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問: d1 i5 w& h9 N0 z+ G
題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常' M4 }; R( Q, Q. O
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位: C- x: R/ a7 S- E2 ^: N
置。(32bit 最多只能定址4GB)
8 ?- I: T- @) c1 M9 k5 ^2 {" m' c2 ~2 n/ t, D f8 T
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
' n. S. M p4 s6 ?; R3 ~5 Z" x |& a以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception9 \# s9 M* P/ _& R, T' ?
vector。
6 N, z, H: s* Y$ y( |, S. ~, }% j3 X5 C
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
$ a% o& i: Z: G) p% H1 X- n" }會比較有感覺。
9 t8 ~9 n# t8 U
/ a0 T" u3 E& {3 |$ X5 wp.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
6 N9 i; r4 p7 }這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會: E1 |! r6 V8 R
再深入討論吧!!
4 F9 H: U+ o0 O4 D7 i p5 ?1 a( q6 B$ z% O
---# q* w' M, I, c7 ]
想知道答案的朋友趕快call in進來
$ w8 H4 n! @/ `2 H) t- r前五名我們有優惠, j# P6 V# V; f2 P; s
現在進一段廣告~ |
評分
-
查看全部評分
|