|
因為再深入我也不懂,所以就淺談吧~
4 w* `. A/ T/ s7 |) M' N$ k& @有錯請指正~$ i' f5 r0 j8 P( g7 V
) K$ b9 Q1 i% e9 n0 }6 l" u話說,身為一個程式設計人員,常常遇到一些程式跑著跑著就當掉的狀況也很合理的。3 E( j4 G) w6 x+ ~4 H
例如:『segmentation fault』。簡單講就是程式寫錯,然後它就當了。
) d2 o& z: S l3 T4 @& K3 [, Y& L, k3 b9 n% r$ |4 d
大家也應該都聽過,『開機之後CPU就會到固定位置去拿指令,然後開始跑,通
; T0 h+ \: b/ V! C5 c常這個位置都是放BIOS,而這個位置通常是0』。
, ~+ _: |, P/ A) Z( s8 u% s8 g3 M3 A2 l6 o! r( V
那這個第一行指令究竟是長怎樣呢?這跟程式當掉有什麼關係?跟程式碼寫錯
, ]6 k( B# F- ?3 p1 Y又有什麼關係?( ^$ h, L' K: y3 b+ J! ]
7 `/ K5 |6 y3 Q3 b! g我們來看通常一般冷開機之後開始跑的程式碼都是怎樣的7 i) B. V" x' d! J9 d r ?, d$ h
( 通常就是跳到bootload or BIOS )* Q |3 p! w8 I
『
8 r2 p; |' K: g1 |9 r) v7 }" rb start, Q; V$ d( c" I% _ @
ldr pc, _undefined_instruction
; f& V F0 g3 b9 _- Pldr pc, _software_interrupt% r' `: z: P4 h+ j4 H: P: M
ldr pc, _prefetch_abort3 P4 D6 a0 m! \6 H" U& T
ldr pc, _data_abort# u) I3 Z$ u* v% W3 U! T
ldr pc, _not_used3 u! }, M7 b# h2 Q$ s1 U U& H* H" M. F
ldr pc, _irq
# I' p) \% {1 Lldr pc, _fiq7 u/ ^4 D3 P1 l5 G: l
』) b% Q' `; X- d4 ^" Z% ^# ~# Q; n
4 }) o% ?; I' t
上面是組語,我們只看兩行,第一行是『b start』,『b』的意思就是branch的 D6 t N& J; g+ E
意思,也就是jump到start這個地方開始執行。換句換說,CPU拿到手的第一個) [2 O+ [' z- }) v. b7 g3 ?; y% o
指令就是要它去找別人,顯然是相當不負責任的行為。讓人不禁懷疑那第二行第1 X5 L% [% |4 R2 x+ N# X5 P4 R
三行到底是幹麼的。
4 R5 @7 g. N" T3 E- }$ b0 H* J- n
我們接著看『ldr pc, _undefined_instruction』,『ldr』的意思是說,將- ~( r( p% i8 ^4 L7 ~- u/ D
_undefined_instruction這個位址,放到pc這個暫存器當中。大家一定也聽過
8 K- o g/ U4 z6 Lprogram counter這個東西,一個正常的CPU就是靠program counter所指" {8 C2 L/ Q6 F& K4 n
的位置去抓指令進來執行。換句話說,第二行程式居然也是要CPU跳到別的地方4 h" c; A7 |: I5 a. [2 A/ w& S
執行。而且前面七八行都是做這件事情。很怪吧?!!!
" A, h# j" C% i
$ I8 d s, \; Z) R B7 f0 i. |0 w到這裡我們解答了上面第一個疑問,第一行程式其實就是一個Jump的指令,跳到' z+ y( Z9 U4 e; a& K8 D
真正的開機程序。
% `4 [) I! C6 c4 L z& x5 \! b) P# @: l
看了程式碼之後,我們不禁好奇這些看起來排列很有規則的程式碼到底是做啥用
0 s2 i* x0 s6 D的?其實答案就是『exception vector』。
, |" {( L" ~% r- U2 J3 @6 V
! \' J; Q0 n/ G什麼是exception vector呢?其實就是CPU出錯了(其實不完全是出錯),它就會9 `5 a H6 }4 I
來這個vector找看相對應的處理函式,例如遇到看不懂得指令,他就固定會抓0x4
' ^4 m i# D6 {; H. `位址的指令,也就是『ldr pc, _undefined_instruction』,接著就會跳到處理undefined instruction的函式去處理。$ r3 ^0 n/ H$ S- O' _; l9 y. `
* v8 }+ j$ t" H- p! X
到這邊我們回答了第二個問題,程式當掉的時候,就是會跑來這個地方,接著再
2 l8 s* Q- Z, t$ VJump到處理的程式碼。同時我們也發現,一個CPU就是靠著這個vector在處理) y% K& U+ L1 |+ }- j
各種不同的exception。那....萬一這些vector被改掉了呢?- |/ k" D; L a z! M
例如:你程式碼拿到一個null pointer,然後又對這個null pointer開始做寫入動
% E$ L; ^& F5 {作。/ O: O1 A5 k1 Y; n# c
: z8 ?! N; ^+ z# {+ g) Nchar *ptr = NULL;
+ b c# N. U) W$ f9 c$ s' `) Mmemcpy( ptr, 0x0, 10 );9 I/ d! \. Z, L3 c1 y
0 A7 T4 j2 o# r$ m0 m$ u- W0 v8 Q那整個OS就完全不能動了。可是我們也知道我們現在這樣寫,頂多 segmentation; u8 x$ X- b, J1 A; \8 }& T/ ?
fault,並不會怎樣,OS還是照樣活著。why why why?
" |1 n5 ?, X' T n原因很簡單,就是這些區段被一些方法保護住了。一般常見的有兩種方法,一種是9 W7 z( u3 O% C6 R) Z! X0 b) d1 x
MMU,一種是cpu有兩個exception vector存上的位址。
3 `1 _# o& k& c9 w9 V; ^; b+ @7 q6 R" b% w0 s& a
MMU可以設定某個區段的存取權力,只能readable的話,那就不會有被改掉的問
7 |! S) j; Z1 |' Q& r# n題,另外一個方式是可以將exception vector的位址擺到不容易改到的地方,通常% S( R# M S9 E! e* k$ y
是往高位址的地方擺(high vector address),例如,0xffff0000接近4GB的位7 Z9 ~1 ~0 @" u2 B9 x- l2 d* C
置。(32bit 最多只能定址4GB)9 M8 |, g% }. T0 h p, Q
7 J+ ^! S! P& U$ Y第二種方式,通常是一開始開機vector還是從0x0那邊抓,可是經過設定CPU,可
$ m& K7 x8 B/ ?以改變,在不斷電的狀態下,發生exception就會跳到高位位址去找exception2 q" ~: D# U2 F! b H7 r: z
vector。
: C3 ` E6 @; o. J$ i6 F: @. B7 N" N5 u) j# ?, K
p.s. 關於定址模式可能有些人沒感覺,可能要懂整個CPU的memory map之後,
9 m7 |6 C& Q" `6 O+ S8 G+ e- e/ s會比較有感覺。
8 @ x# D3 M2 a6 u# |( D
2 o- e5 _ y: ]! G) q9 c! kp.s. 眼尖的人一定覺得很怪,為什麼vector第一行用『b』,其它卻是用『ldr』,
4 ]( t5 J; h+ ?8 \! b& `這個牽涉到本身指令的不同和程式碼是不是relocatable的程式有關,將來有機會+ V' l9 S) \) }& S( Y" O8 m$ R
再深入討論吧!!
5 f6 R$ d, D7 ~/ E. K% w; A( n: f1 h) s* d9 E, ^8 e
---0 T. S( @# j& c# I
想知道答案的朋友趕快call in進來
K; {* t5 G* a0 Q. b. M5 x( Y2 i0 _前五名我們有優惠
2 R! ^! Y4 ?9 Z3 o3 ~" v1 ^# K現在進一段廣告~ |
評分
-
查看全部評分
|