ARM彙編程序設計學習筆記(一)
爲了學習android系統,發現需要學習linux驅動,發現學習linux驅動,需要先知道處理器的各種架構,爲了學習此種知識,發現網上有很多mini2440相關的知識,因此,將其作爲藍本,認真學習。直到linux驅動的學習完成。
這是linux驅動學習的第一部分,arm的彙編程序。
本文檔的大部分資料翻譯於《S3C2440A 32-BIT CMOS MICROCONTROLLER USER’S MANUAL》
一.編程模型
處理器工作狀態
從程序員的角度來看,ARM920T(s3c2440的內核)有如下兩種狀態:
- ARM狀態,執行32位,字對齊的指令
- THUMB狀態,執行16位,半字對齊的THUMB指令。
注意:這兩種狀態的切換,不會影響處理器的模式和寄存器狀態
1.1 切換狀態
進入THUMB狀態
將操作數寄存器的第0位,設爲1,然後執行BX指令,就可以切換爲THUMB狀態。
例如:
BX Rm;如果Rm的第0位,是1,則跳轉到Rm所在的地址,並且設置處理器在thumb模式下
如果在THUMB狀態下,進入了異常,從異常中退出,依然是THUMB狀態
進入ARM狀態
可以通過下面的方法,進入arm狀態:
- 將操作數寄存器的第0位,清零,然後執行BX指令
BX Rm;如果Rm的第0位,是0,則跳轉到Rm所在的地址,並且設置處理器爲arm模式下
- 處理器發生異常時,PC被放置在異常模式下的連接寄存器中,然後從異常向量地址開始執行
1.2 內存格式
ARM920T 將內存視爲一個線性的字節序列。字節地址從0開始。0到3字節保存第一個字。4到7字節保存第二個字,依次類推。這些字支持小端和大端格式。
1.3 指令長度
指令長度爲32位長(arm模式)和16位長(thumb模式)
1.4 數據類型
ARM920T 支持字節(8位)、半字(16位)、字(32位)數據類型。字必須4字節對齊。半字必須兩字節對齊。
1.5 運行模式
ARM920T 支持7種運行模式:
- User(usr):最普通的arm執行狀態
- FIQ(fiq):被用來進行數據傳輸,和信道處理
- IRQ(irq):通用的中斷處理
- Supervisor(svc):爲操作系統設計的保護模式
- Abort mode(abt):數據和指令預取發生問題時,進入
- System(sys):爲操作系統設計的特權用戶模式
- Undefined(und):當一個未定義的指令執行時,進入此模式
模式的改變可以通過軟件控制,也可以通過外部的中斷,或者異常。大多數的應用程序將運行在用戶模式下。
特殊模式(非用戶模式)僅僅在服務中斷或者異常,或者訪問受保護的資源時纔會進入。
1.6 寄存器
ARM920T 總共有37個寄存器。其中,31個通用的32位寄存器和6個狀態寄存器。這37個寄存器,對於程序來說,不能同時可見。
處理器狀態和運行模式,決定了那些寄存器對於程序員來說可見。
1.7 arm狀態下的寄存器集
在arm狀態下,程序員只能看到16個通用寄存器和1個或者2個狀態寄存器。在特殊模式(非用戶模式),相應的寄存器組被切換。圖2-3展示了在每種模式下那些寄存器可見。這些寄存器組使用一個陰影三角形標記:
arm狀態下的寄存器組包含16個可直接訪問的寄存器:R0-R15.除了R15寄存器以外,其他的寄存器都是通用寄存器。可以用來存儲數據或者地址。
除此之外,還有第十七個寄存器用來存儲狀態信息。
寄存器 | 描述 |
---|---|
寄存器14 | 該寄存器作爲子程序的鏈接寄存器。當分支指令(Branch)和連接指令(BL)執行時,這個寄存器保存R15的值.其他時候,可以被作爲通用寄存器來使用。對應的寄存器有:R14_svc,R14_irq,R14_fiq,R14_abt,R14_und,他們都在對應的模式下保存R15的值 |
寄存器15 | 這個寄存器爲程序計數器(PC)。在arm模式下,bits[1:0]是0,bits[31-2]保存PC。在thumb模式下,bit[0]爲0,bits[31:1]保存PC |
寄存器16 | 這個寄存器是CPSR(當前程序狀態寄存器)。它保存代碼的各種flag和一些模式位 |
FIQ模式有7個寄存器,被映射爲R8-R14(R8_fiq-R14_fiq).在arm模式下有許多FIQ處理程序不需要保存的寄存器。
而USer,IRQ,SuperVisor,Abort和Undefined模式,都有R13和R14,並且允許他們有自己的堆棧指針和鏈接寄存器
ARM和THUMB之間的寄存器關係
如下:
- THUMB模式下R0-R7 ,ARM模式下R0-R7 完全相同
- THUMB模式下CPSR和SPSRs,ARM模式下CPSR和SPSRs是完全相同的
- THUMB模式下SP映射爲ARM的R13
- THUMB模式下LR映射爲ARM下的R14
- THUMB模式下PC映射爲ARM的R15
在thumb模式下訪問高寄存器組(Hi-registers)
在THUMB模式下,寄存器組R8-R15(被稱爲Hi-registers)不是標準寄存器組中的一部分。因此,彙編程序對他的訪問是受限制的。但是他們可以用來作爲臨時的存放地。
可以使用mov指令,將R0-R7裏面的值放置到高寄存器中。也可以將高寄存器中的值放到低寄存器中(R0-R7)
也可以使用CMP指令,將高寄存器和低寄存器進行比較
也可以使用ADD指令,將高寄存器中的值加到低寄存器中
1.8 程序狀態寄存器
ARM920T 包含一個當前程序狀態寄存器(CPSR),以及5個已經保存了的程序狀態寄存器(SPSR)。這些寄存器的功能有:
- 保存執行單元(ALU)最近的信息
- 打開或者關閉中斷
- 處理器運行模式
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
N | Z | C | V | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | I | F | T | M4 | M3 | M2 | M1 | M0 |
條件碼標識
N,Z,C,V是條件碼的標誌位。這些將會被算術和邏輯運算改變,然後再根據這些位來決定指令是否執行。
在arm狀態下,所有的指令可以被條件的執行。
在thumb狀態下,只有分支指令纔可以按照條件執行
控制位
最低下的8位被稱爲控制位。當一個異常發生時,他們會被改變。如果處理器在特權模式下,那麼他們也可以被軟件手動改變。
位 | 描述 |
---|---|
T | 當爲1時,處理器運行在THUMB模式下,否則運行在ARM模式下。他將影響TBIT外部信號 |
中斷禁止位 | I和F是中斷禁止位。爲1,則相應的禁止IRQ和FIQ |
模式位 | M4,M3,M2,M1,M0是模式位,如下表,只有下表出現的模式纔是正確的模式,一旦程序設置了錯誤的模式,則會產生復位異常 |
保留位 | 剩下的位爲保留位。 |
M[4:0] | 模式 | thumb模式下的寄存器 | arm模式下的寄存器 |
---|---|---|---|
10000 | User | R7…R0,LR,SP,PC,CPSR | R14…R0,PC,CPSR |
10001 | FIQ | R7…R0,LR_fiq,SP_fiq,PC,CPSR,SPSR_fiq | R7…R0,R14_fiq…R8_fiq,PC,CPSR,SPSR_fiq |
10010 | IRQ | R7…R0,LR_irq,SP_irq,PC,CPSR,SPSR_irq | R12…R0,R14_irq,R13_irq,PC,CPSR,SPSR_iraq |
10011 | Supervisor | R7…R0,LR_svc,SP_svc,PC,CPSR,SPSR_svc | R12…R0,R14_svc,R13_svc,PC,CPSR,SPSR_svc |
10111 | Abort | R7…R0,LR_abt,SP_abt,PC,CPSR,SPSR_abt | R12…R0,R14_abt,R13_abt,PC,CPSR,SPSR_abt |
11011 | Undefined | R7…R0,LR_und,SP_und,PC,CPSR,SPSR_und | P12…R0,R14_und,R13_und,PC,CPSR |
11111 | System | R7…R0,LR,SP,PC,CPSR | R14…R0,PC,CPSR |
1.9 異常
例如響應外設電路的中斷,此時反生異常。在異常處理前,當前處理器的狀態必須保存下來,目的是,當異常處理完成之後,可以繼續執行
在同一時間,可能同時出現多個異常,此時他們以固定的順序進行處理,詳見下面的異常優先級。
進入異常時的操作
當處理異常時,ARM920T會做如下的操作:
- 在鏈接寄存器中保存下一個指令的地址。如果異常從arm狀態進入,則下一個指令的地址被複制到鏈接寄存器中(即PC+4,或者PC+8,具體依賴於不同的異常,後面有詳細說明)如果異常從THUMB狀態進入,鏈接寄存器則保存當前PC的偏移量。這就意味着,異常處理程序,不用管,到底是從哪個狀態進入的異常。
- 賦值CPSR到對應的SPSR
- 修改CPSR對應的模式位
- 修改PC爲對應的異常向量地址
還可以設置異常禁止位,防止異常嵌套的發生
如果處理器在THUMB狀態下,此時發生了異常,當PC指向異常向量的地址時,自動切爲ARM狀態
離開異常時的操作
異常處理程序完成後:
- 將鏈接寄存器的值,複製到PC中
- 複製SPSR到CPSR
- 如果允許中斷,則清除中斷禁止位,
異常入口/出口摘要
下表列出了異常發生時,保存在鏈接寄存器中的PC的值,以及退出異常處理程序的推薦的指令
返回的指令 | arm R14_x | thumb R14_x |
---|---|---|
BL;MOV PC,R14 | PC+4 | PC+2 |
SWI;MOVS PC,R14_svc | PC+4 | PC+2 |
UDEF;MOVS PC,R14_und | PC+4 | PC+2 |
FIQ;SUBS PC,R14_fiq,#4 | PC+4 | PC+4 |
IRQ;SUBS PC,R14_irq,#4 | PC+4 | PC+4 |
PABT;SUBS PC,R14_abt,#4 | PC+4 | PC+4 |
DABT;SUBS PC,R14_abt,#8 | PC+8 | PC+8 |
RESET;NA | - | - |
FIQ
FIQ(快速中斷異常)被設計來處理數據傳輸和信道處理。在arm模式下,保證有最小,且足夠的寄存器可用,以達到最優的上下文切換
外部的nFIQ輸入爲低時,產生FIQ異常。根據ISYNC輸入信號的狀態,nFIQ的輸入可以被處理爲同步或異步。當ISYNC爲低時,nFIQ和nIRQ被當做異步。同步的週期延遲發生在中斷影響處理器流之前。
無論異常是從ARM狀態還是thumb狀態進入的,FIQ異常可以通過下面的指令退出異常處理流程:
SUBS PC,R14_fiq,#4
FIQ可以通過CPSR的F位來禁止(用戶模式下無法操作)。如果F位爲0,ARM920T在每條指令結束時檢查FIQ同步器輸出的低電平。
IRQ
IRQ就是常見的中斷,它由nIRQ輸入觸發。IRQ的優先級比FIQ的優先級低並且當FIQ進入時,IRQ將被禁止。通過設置CPSR寄存器的I位,可以在任何時候在特殊模式下(非用戶模式)禁止這個異常
可以執行下面的代碼,返回異常:
SUBS PC,R14_irq,#4
Abort
當前內存訪問無法完成時,產生一個Abort異常。它也可以由外部的ABORT輸入產生。ARM920T在內存訪問週期中,檢查abort異常
兩種abort異常:
- 預取址Abort:在指令預取址的時候發生
- 數據Abort:數據訪問時發生
如果預取址Abort發生,則取到的指令被標記爲非法指令,並且直到指令到達管道的頭部才發生異常。
如果指令沒有被執行,abort也不會產生,比如分支指令
如果數據abort發生,接下來會發生什麼,則依賴於指令的類型:
- 但數據傳輸指令(LDR,STR)寫會被修改的寄存器。abort異常處理程序必須清楚這一點
- 交換指令(swap)中止,就好像它沒有被執行一樣
- 塊數據傳輸指令繼續完成(LDM,STM)。如果回寫位被置位,則基址寄存器被更新。如果指令要覆蓋基址寄存器,則覆蓋會被中止,以保證不會覆蓋。一旦發生abort異常,所有的寄存器覆蓋都會被中止。因此R15就會被保留
abort機制可以實現按需分頁的虛擬內存系統。在這個系統中,處理器可以產生任意的地址。當數據地址無效時,內存管理單元(MMU)產生一個abort異常。然後abort異常處理程序找出abort的原因,讓請求的數據可用,然後重新執行產生abort異常的指令。
應用程序不需要知道他可用的內存量,他的狀態也不會受abort異常的任何影響
退出abort異常的指令爲:
SUBS PC,R14_abt,#4;for a prefetch abort
SUBS PC,R14_abt,#8;for a data abort
然後恢復PC和CPSR,並且再次執行產生abort異常的指令
軟件中斷
軟件中斷(SWI)被用來進入Supervisor模式。軟件中斷通過下面的指令返回:
MOV PC,R14_svc
他們恢復PC和CPSR,然後繼續執行SWI後面的指令
未定義指令
當arm920T無法處理一個指令時,產生一個未定義指令異常。這種機制可以被用來擴展THUMB和ARM指令的軟件仿真。
可以執行下面的指令,退出異常:
MOVS PC,R14_und
恢復CPSR,然後執行產生未定義指令異常的下一條指令
異常向量表
下表展示了異常向量地址:
地址 | 異常 | 進入的模式 |
---|---|---|
0x00000000 | Rest | Supervisor |
0x00000004 | Undefined instruction | Undefined |
0x00000008 | Software Interrupt | Supervisor |
0x0000000C | Abort(prefetch) | Abort |
0x00000010 | Abort(data) | Abort |
0x00000014 | Reserved | Reserved |
0x00000018 | IRQ | IRQ |
0x0000001C | FIQ | FIQ |
異常優先級
當同時產生異常時,系統以固定的順序處理。
高優先級:
- Rest
- Data abort
- FIQ
- IRQ
- Prefetch abort
低優先級:
- Undefined instruction,Software Interrupt
注意:並不是所有的異常都能同時發生
未定義指令和軟件中斷異常他們是互斥的
如果數據abort異常和FIQ異常同時發生,並且FIQ異常被允許,ARM920T進入數據abort異常處理程序,然後立刻去處理FIQ的異常。FIQ異常退出之後,繼續在abort異常處理程序中執行。
數據abort的優先級高於FIQ是有道理的,他能夠保證第一時間捕獲到傳輸錯誤。進入這個異常的時間,應該加上FIQ的延遲。
中斷延遲
如果FIQ打開,則最長的延時包括:傳遞給同步器(Tsyncmax)的最長請求時間,加上,最長的指令時間(Tldm),加上,數據abort進入的時間(Texc),加上FIQ進入的時間(Tfiq)。然後纔是ARM920T在0x1c處執行。
Tsyncmax三個處理器週期,Tldm20個處理器週期,Texc3個處理器週期,Tfiq2個處理器週期。總共需要28個處理器週期。在一個連續的20Mhz的處理器上大約消耗1.4微秒。
最大的IRQ延遲計算方式跟上面類似。但是必須考慮到FIQ有更高的優先級,可以延遲任意時間進入IRQ異常處理程序。
FIQ和IRQ的最小時間則由Tsyncmin加上Tfiq組成,爲4個處理器週期。
復位異常
當nREST輸入爲低時,ARM920T放棄執行指令,然後繼續從遞增的字地址中取指令。
當nRest再次變高,ARM920T:
- 將當前的PC和CPSR,寫入到R14_svc和SPSR_svc。
- 將M[4:0]改爲1011(supervisor模式),CPSR的I,F位置位,清楚CPSR的T位
- 將PC爲0x00
- 在arm模式下,繼續執行