1. 程式人生 > >深入淺出嵌入式底層軟體開發

深入淺出嵌入式底層軟體開發

1.1 ARM CPU暫存器

ARM的彙編程式設計,本質上就是針對CPU暫存器的程式設計,所以要搞清楚ARM有哪些暫存器;ARM暫存器分為兩類:普通暫存器和狀態暫存器;普通暫存器一共有16個,分別為R0——R15,狀態暫存器有2個,分別為CPSR和SPSR。

R15別名PC(program Counter),中文稱程式計數器,它的值是當前正在執行的指令在記憶體中的位置,而當指令執行結束後,CPU硬體會自動將PC值加1,使PC指向下一條即將執行的指令,因此,當對PC暫存器賦值時,也就相當於完成了一次無條件跳轉;

R14別名LR(Linked Register),中文稱為連結暫存器,用於存放子程式的返回地址,與子程式呼叫密切相關,下面用例子說明LR如何被使用

彙編器會將例子中的第4行編譯為指令:BL addsub,將11行編譯為:MOV pc,lr;其中,BL addsub會完成兩件事:

1)將子程式的返回地址(也就是第5行程式碼在記憶體中的位置)儲存到暫存器LR中;

2)跳轉到子程式addsub的第一條指令處,完成了子程式的呼叫;

而指令MOV pc, lr 則將儲存在LR中的返回地址賦給PC,這樣就完成了從子程式的返回。

如果我們呼叫的子程式又呼叫了孫子程式,該怎麼辦?如果我們寫的是C程式,就完全不用管,因為編譯器為我們提供了方案:編譯器會在孫子程式的入口處增加入棧操作,將LR的值入棧,然後在孫子程式的返回處增加出棧操作,將LR的值恢復;如果編寫彙編程式,一定要在子程式的入口處儲存LR暫存器的值。

R 13 別名SP(stack pointer),中文名稱棧指標暫存器,它是用來存放堆疊的棧頂地址的,也就是說,每次進行出棧和入棧的時候,都將根據該暫存器的值來決定訪問記憶體的位置。32位ARM指令集中沒有專門的入棧和出棧指令,所以並不是一定要用SP來作為棧指標暫存器,除了PC外,任何了普通暫存器都可以作為棧指標暫存器,只不過約定俗成都是用SP罷了。

R0——R12是普通暫存器,可以用於任何地方。

狀態暫存器CPSR(Current Program Status Register)中文名稱 當前程式狀態暫存器,也就是說它是用於儲存程式的當前狀態的,如下圖

1)條件程式碼標誌位,它們是ARM指令條件執行的依據

①  N:運算結果的最高位反映在該標誌位:對於有符號二進位制補碼,結果<0,N =1;結果>=0, N  = 0;

②  Z:指令結果為0時,Z =1,(通常表示結果“相等”),否則 Z = 0;

③  C:當進行加法運算並且最高位產生進位時C=1,否則,C =0;減法產生借位C=0,否則C=1;移位操作C表示從最高位最後移出的值,其他指令C通常不變

④  V:當進行加減法運算,並且發生有符號溢位時 V =1,否則 V =0

2)控制位,它們將控制CPU是否響應中斷

I:中斷禁止位,當I位為1時,IRQ中斷被禁止

F:快中斷禁止位,當F為1時,FIQ中斷被禁止

T:反映了CPU當前狀態,當T為1時,處理器執行在Thumb狀態下,當T為0時,執行在ARM狀態

3)模式位,包括M4,M3,M2, M1,M0,這些位決定了處理器的模式,總共有7種模式:使用者、快中斷、中斷、管理、中止、未定義、系統

SPSR(Saved Program Status Register)中文名稱:儲存的程式狀態暫存器,該暫存器的結構和CPSR完全一樣,在異常發生時,由硬體自動將異常前的CPSR的值存放到SPSR中,以便將來在異常處理結束後,程式能恢復原來CPSR的值

1.2 流水線對PC的值的影響

從圖中可以看出CPU內部主要有3部分:指令暫存器、指令譯碼器、指令執行單元(包括ALU和通用暫存器組)。CPU在執行一條指令的時候,主要有3個步驟:取指(將指令從記憶體或指令cache中取入指令暫存器),譯碼(指令譯碼器對指令暫存器的指令進行譯碼操作,從而辨識出該指令時要執行add還是sub,或是其他操作,從而產生各種時序控制訊號),執行(指令執行單元根據譯碼的結果進行運算並儲存結果)。CPU序列執行程式會特別慢,因為執行指令的3個步驟佔用的CPU硬體完全不同,所以,在對第一條指令進行取指操作的時候,同時可以對第二條指令進行譯碼操作,對第三條指令進行執行操作,這種並行執行指令的方式稱作流水線操作。PC總是指向“正在取指”的指令,而不是指向“正在執行”的指令或正在“譯碼”的指令。一般來說,人們習慣性約定將“正在執行的指令作為參考點”,稱之為當前第一條指令,因此PC總是指向第三條指令。當ARM狀態時,每條指令為4位元組長,所以PC始終指向該指令地址加8位元組的地址,即:PC值=當前程式執行位置+8;