nbsp; undefexception sub lr, lr, #4 ; (lr) = address of undefined instruction stmdb sp, {r0-r3, lr} mov r1, #id_undef_instr b commonhandler entry_end undefexception 上面就是undef exception的服務(wù)程序的入口處(已經(jīng)將不參與編譯和thumb模式下的代碼去掉),通過lr-=4計(jì)算出觸發(fā)異常前的指令地址,同時(shí)保存r0-r3和lr入undef_exception stack用于最后恢復(fù)現(xiàn)場(chǎng)和取得異常指令本身,隨后進(jìn)入分發(fā)程序commonhandler.commonhandler是一個(gè)公共的異常服務(wù)程序,它通過不同的傳入?yún)?shù)來進(jìn)行處理,在這里mov r1,#id_undef_instr就是指定異常模式為undef exception. 2-2.swi服務(wù)程序 按在arm處理器的設(shè)計(jì)意圖,系統(tǒng)軟件的系統(tǒng)調(diào)用(systemcalls)都是通過swi指令完成。swi相當(dāng)于一個(gè)中斷指令,不同的是swi不是由外部中斷源產(chǎn)生的,同時(shí)對(duì)應(yīng)于swi的異常向量位于0xc的位置或0xffff 000c的位置。也就是說當(dāng)執(zhí)行一個(gè)swi指令后,當(dāng)前程序流中斷,并轉(zhuǎn)入0xc或0xffff000c執(zhí)行,同時(shí)將cpsr_mode(當(dāng)前程序狀態(tài)寄存器)復(fù)制入spsr_svc,轉(zhuǎn)入svc模式運(yùn)行(使用特權(quán)模式的寄存器組)。也就是說系統(tǒng)通過執(zhí)行swi引發(fā)系統(tǒng)swi異常后切換入特權(quán)模式,系統(tǒng)調(diào)用功能號(hào)由swi xx后的xx決定,在運(yùn)行完指定功能的代碼后返回異常時(shí)的地址并恢復(fù)用戶模式。我們看看,wince中這部分代碼是如何實(shí)現(xiàn)的。 dcd swihandler ; svc<<--------------------------swi入口點(diǎn)。 leaf_entry swihandler if ... endif movs pc, lr entry_end swihandler 上面if 到endif之間的代碼在編譯的時(shí)候是得不到編譯的(事實(shí)上這部分代碼是用于開發(fā)中調(diào)試使用的,針對(duì)特殊的硬件平臺(tái),一般與我們使用的硬件平臺(tái)無關(guān)。所以下面摘抄的代碼都不將不參與編譯的內(nèi)容寫入),因此swi服務(wù)程序就是一句話。movs pc, lr也就是直接回到swi的地方,同時(shí)將spsr_svc恢復(fù)到cpsr_mode中。這個(gè)過程中并沒有進(jìn)行在系統(tǒng)態(tài)執(zhí)行特定系統(tǒng)指令序的工作,而僅僅是簡(jiǎn)單的返回,所以這不是系統(tǒng)調(diào)用,系統(tǒng)調(diào)用還需要根據(jù)調(diào)用號(hào)的不同運(yùn)行指定的核心態(tài)代碼。也就是說wince的系統(tǒng)調(diào)用不是通過swi來完成的,而是通過其他的異常處理手段達(dá)成的。 2-3 中斷服務(wù)程序
irq(大概是最熟悉的異常方式了)在外部中斷源在需要向處理器請(qǐng)求服務(wù)時(shí)發(fā)生,比如:時(shí)鐘、外圍器件fifo上/下溢出、按鍵等等。irqhandler就是中斷的處理句柄,下面我們來具體看看。 ---------------------------------------------------------------------------------- nested_entry irqhandler sub lr, lr, #4 ; fix return address stmfd sp!, {r0-r3, r12, lr} ;保存將要用到的寄存器和lr壓入stack_irq prolog_end 和上面一樣,服務(wù)程序的入口處都是例行公事的計(jì)算返回位置以抵消流水線誤差。再將要用到的寄存器壓入stack_irq,這樣,準(zhǔn)備工作就做完了。 ; test interlocked api status. ;interlocked_start equ user_kpage+0x380 ;interlocked_end equ user_kpage+0x400 sub r0, lr, #interlocked_start cmp r0, #interlocked_end-interlocked_start bllo checkinterlockedrestart 上面這部分的內(nèi)容是關(guān)于互鎖的檢測(cè),由于如信號(hào)量這些同步手段都必須作為原子操作進(jìn)行,不允許打斷。所以如果中斷發(fā)生在互鎖api的執(zhí)行過程中,就需要專門的處理了。這些api都是放在interlocked_start和interlocked_end之間的,通過lr很容易就檢查出是否是interlockedxxx的過程中。這里并不關(guān)心互鎖的實(shí)現(xiàn)就繞開這部分代碼繼續(xù)往下看,當(dāng)作中斷沒有發(fā)生在interlock過程處理。 ; ; careful! the stack frame is being altered here. it"s ok since ; the only routine relying on this was the interlock check. note that ; we re-push lr onto the stack so that the incoming argument area to ; oeminterrupthandler will be correct. ; mrs r1, spsr ; (r1) = saved status reg stmfd sp!, ; save spsr onto the irq stack mov r0,lr & |