|
因為再深入我也不懂,所以就淺談吧~* @$ ^ k3 ]8 `6 S9 H, X
有錯請指正~
$ _5 p, B0 _1 S) r( {! D
" T. B' [/ V, N/ g0 H- P& y/ n話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。
2 N6 u9 d& r4 a3 o, K- q/ u, P9 c& }例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
" N- P& f# ?. P: ?/ m! Z; h2 H( F$ R4 {: i5 e) J: O
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通
' L: [7 ]0 @0 |0 w0 r常這個位置都是放BIOS,而這個位置通常是0』。% t- _1 t+ X: Z4 j
6 V! S5 K: O, }/ f9 Y2 u2 \
那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯8 @! g. T4 w! [5 o7 [4 _1 D
又有什麼關係?+ V/ M) t8 N* ~& S5 X
; A( E3 v% U P- b* u2 Y我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的% ]1 L/ g# t% n
( 通常就是跳到bootload or BIOS )
; e( _0 `4 R2 q8 P) z/ O9 S1 F『' o, e' M w C
b start
0 [- A$ e- E" s4 qldr pc, _undefined_instruction
3 ]3 n" M5 a1 {+ g0 W4 Z+ _ldr pc, _software_interrupt
' J& t/ r- h$ j# Vldr pc, _prefetch_abort
2 S! H4 N+ J5 _/ Q# ~! {/ a. dldr pc, _data_abort% Q3 O, I) E# x( V
ldr pc, _not_used
/ h' z3 }! h* e$ p% J6 Z) E/ K+ Wldr pc, _irq3 J" k/ s+ J" Y. y) Y
ldr pc, _fiq8 D% L4 f& F7 ]( |' r
』
. _0 G6 }3 [, l1 h2 U% D' V, Y5 ?, I, H* w5 G8 |
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的( f# P& ^: v) ~! }
意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個, a! F. Q7 c9 G3 Q# Z1 c( U
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第
- b/ Q9 ?2 H1 A6 r三行到底是幹麼的。3 H& O3 U0 C/ h6 w- W. a' i+ x
. ]& V9 B5 X, A- x3 m
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將
9 k! t w. E3 C/ q_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過
/ y5 _8 ~! h+ v) O& ^& hprogram counter這個東西,一個正常的CPU就是靠program counter所指
$ B) w a: d( m2 J" j5 ?的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方. `* M* H3 r1 o+ }- P. H( V
執行。而且前面七八行都是做這件事情。很怪吧?!!!
+ l8 @+ }. @# [) K I
" S, Y/ C& V' ]: m到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到
: D" c% X: w3 C' n F- j# @5 _真正的開機程序。
9 _- v8 z' H9 d
& i E# b& S1 z; l看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用3 i* x3 x- ^6 j. I0 D. k; L
的?其實答案就是『exception vector』。" w9 R9 ?5 D$ O
9 y7 W8 N7 l9 L! s! h' U什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會, x( E j' r& s' q
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4
3 A3 |6 d/ \- P: z: u" F位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。3 B; J0 q% e9 L2 |8 l
{# `% {: h$ ^到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再/ a9 Z, ~: h3 Z, x0 {$ s! y
Jump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理7 t) F" H5 t3 T- j4 x
各種不同的exception。那....萬一這些vector被改掉了呢?$ G0 n1 d% Q- _9 ]. V, ]
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動. c, n: b4 Z& G+ v' s
作。3 D% v1 G0 j+ h# C+ t" p$ b2 m o
! K% D2 ]' k2 R( G6 ]char *ptr = NULL;
2 a' O4 _) R9 `1 ?2 i. Omemcpy( ptr, 0x0, 10 );
& `2 Y+ \3 e# N
- i: {0 j3 H0 t. H! K% U1 `! e7 r那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation) S. C X9 h; u: P6 m1 u
fault,並不會怎樣,OS還是照樣活著。why why why?; h& ~1 m- K) d& s: R/ w1 b
原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是! ]# B/ {/ n& w9 y' {
MMU,一種是cpu有兩個exception vector存上的位址。* {, r/ G( a0 m
' W. a& w7 ~4 e& w" }MMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
" W; w1 q+ z: }8 h7 U3 d題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常8 t8 x7 n& m( }& d5 k
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位% M% C0 @ R( u% H( ]' @
置。(32bit 最多只能定址4GB): N) I* D3 h5 C6 Y6 B' ?
# p! P, K! [* O' V7 ]
第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可& l1 m) }5 f' x
以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception' D9 t5 E1 X# J7 a* t2 n; w* I `
vector。* W$ n, T* K& P4 J+ u6 o- @
- F( I( v+ s& f6 J$ N& o6 n, ip.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
& p; [3 _# `: R3 u會比較有感覺。
, Z- o5 c, Z1 ]( ~4 v
* d8 A+ o; a. j' }p.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,, A( b3 H( \& c* l- J* Z7 j
這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會
/ ^: p) Q& X- O a: ?再深入討論吧!!
9 b6 G3 u/ C' j) I- v, B5 |8 b9 `
---% t, L6 n- P1 a
想知道答案的朋友趕快call in進來
- K( l- d) a( y' I前五名我們有優惠
0 n' n Z' r. b現在進一段廣告~ |
評分
-
查看全部評分
|