|
因為再深入我也不懂,所以就淺談吧~/ Z9 R- K' t$ b, Y( ~ n2 z
有錯請指正~0 N4 q2 E3 j6 O
2 d- X3 k, p# s. Y( Q話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。. _$ p$ Y8 R; ?$ J3 U. `
例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
( M; l3 `. Y6 \, r2 t; y) G' [
7 B# ^- Y; N. A' v d/ w大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通( s: w& ]0 y4 [) c& U/ {
常這個位置都是放BIOS,而這個位置通常是0』。4 M3 A. w% P5 b2 n
) |4 A- v5 h( m" q: c
那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯3 j9 N8 B, k! X: j# P
又有什麼關係?
9 D& Q4 C' B* R d5 c' ~
& ~6 v: ?( R9 U4 X我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的
0 l$ W; V- A+ W" C; S7 F0 k- O5 b. F( 通常就是跳到bootload or BIOS )( f9 T/ X" i4 c, \# y, i, V% h
『
. y$ E0 g0 ^) C3 T* mb start
# E7 G' {7 w4 k: b# V+ }$ g9 Jldr pc, _undefined_instruction
9 q, G6 J7 G: i+ t, |: ~ldr pc, _software_interrupt% r% {$ N9 H, I5 n/ j
ldr pc, _prefetch_abort
, w k1 q. R- i% A5 c" G. Lldr pc, _data_abort
1 Q( w7 ~+ M5 R( Q) M# \, }ldr pc, _not_used `/ N w) g( W, z/ _+ x$ c
ldr pc, _irq
M( M* s! O; t* T) Wldr pc, _fiq( @; M3 x* Q9 Z! C$ D% b2 B+ X; ~
』: f7 D3 p1 j5 E- A
! ~1 C. C: R3 a2 w! y+ n3 Z) e0 h k% R" D
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的# L8 ]8 I1 a9 c/ e! x# O
意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個# e# M: R1 Z. { f" z9 {
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第
, l& Z) {5 R& s& g三行到底是幹麼的。2 Q% S A, f9 g9 e4 f0 _/ c
|" {5 F( _; M/ |. T
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將
# S4 u" G' r9 U6 J, y( O: v_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過5 l+ M2 l% Z# X* X. K/ b, a7 m
program counter這個東西,一個正常的CPU就是靠program counter所指1 Y+ G9 s- ` C& X! b% m- d: T: n
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方
' {8 N* d8 j4 r& P2 Q4 X執行。而且前面七八行都是做這件事情。很怪吧?!!!
; X, S5 N# j- g
# J/ B8 F, s7 X0 y/ ^5 I& o到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到2 w0 O8 } ]8 W" W7 [
真正的開機程序。
4 k& O/ B. J1 K. d+ x7 u1 e7 }6 C% k% v4 _
看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用
! P1 R$ t3 ?" I' ]+ ]6 o的?其實答案就是『exception vector』。
( J, E- W. c* Z3 Q+ u6 Q3 q) i" t/ V! ], I5 x
什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會
/ Z2 e5 v" W/ _! G5 `來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x47 I& }/ }3 e! r6 f/ L" Z
位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。
' U0 r+ i) U0 K7 m- c. T
- r {# `% @/ W- C0 `+ Y到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再. q7 ]% K% \* k$ c) k! {/ v
Jump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理
7 H0 _; _. j# d! \( O各種不同的exception。那....萬一這些vector被改掉了呢?; Q N) q. [' [7 N- h
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
C( X' C) ], s8 K作。
7 j$ l/ |% R e5 c9 s, d' U# i1 F. U5 E; q5 Y
char *ptr = NULL;6 J3 @1 H: u4 J. `6 C) T
memcpy( ptr, 0x0, 10 );
' Q5 G/ z& z3 f
% Z0 }/ ]; i6 l% k( ` O9 E那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation
1 \( B1 j+ I/ Q$ e- Z, u5 Lfault,並不會怎樣,OS還是照樣活著。why why why?
+ k5 q! S! z+ d: d% f原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是
4 L# q! p& y2 j4 ?6 p: cMMU,一種是cpu有兩個exception vector存上的位址。
3 b, Y) G* t# e9 a/ f6 U" q
0 P3 Y- D: Z: x: \) L5 IMMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
- R/ n. A( ]$ C! @' Q. ]4 S$ R5 R題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常" O5 }% Y( `4 x+ h5 G) U
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位
0 [6 r; E& J8 j& n4 W1 r0 }置。(32bit 最多只能定址4GB)
N J& ^. S2 h- K9 d+ N" F
. p# W5 W: j ^' y' M第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可8 H* c4 M* W- g
以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception
" @- G' x2 @+ I) G- ]vector。
' M K; D, |% ^3 ^7 ? T# z C# M) p) V' r5 s
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,8 n+ {6 z7 v4 `7 m7 j
會比較有感覺。. O7 u1 Q m ^. [* P8 y
( J* d; ~. B) k$ y) i7 G. `1 @- N
p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
5 I8 h+ s( B5 z$ W. V6 }4 U" B這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會9 Q5 ~' j, b& Q6 o' g7 l) J+ L
再深入討論吧!!& U6 [" X$ ?8 N7 q9 p/ g
4 O4 q' a, k% s- {---3 r( S, B' ~! P6 F$ f# O' O
想知道答案的朋友趕快call in進來
z- s8 s' I' a# _3 P+ z9 u前五名我們有優惠
$ p" Y3 O* q, r/ S1 G# o' O現在進一段廣告~ |
評分
-
查看全部評分
|