ARM架構與體系學習(一)——初識啓動文件

首先決定看ARM模板的啓動文件,光這個啓動文件就不簡單啊,由於ARM彙編不瞭解,看見一個彙編詞都是翻閱手冊,不懂的就上網或者看書查找,爭取明瞭。編程

首先就是啓動代碼的做用,它包含了異常向量入口,還有初始化了堆棧。啓動代碼的開始時定義了一些堆棧的大小。函數

FIQ_STACK_LEGTH         EQU         0
IRQ_STACK_LEGTH         EQU         9*8             ;每層嵌套須要9個字堆棧,容許8層嵌套
ABT_STACK_LEGTH         EQU         0
UND_STACK_LEGTH         EQU         0

至於大小爲何這麼設定,暫時還不知道。接着是一些ARM模式的定義

NoInt       EQU 0x80

USR32Mode   EQU 0x10
SVC32Mode   EQU 0x13
SYS32Mode   EQU 0x1f
IRQ32Mode   EQU 0x12
FIQ32Mode   EQU 0x11

而後是一些啓動文件中須要用到的外部聲明有外部文件須要用到的啓動文件中的標號聲明。

;引入的外部標號在這聲明
    IMPORT  FIQ_Exception                   ;快速中斷異常處理程序
    IMPORT  __main                          ;C語言主程序入口 
    IMPORT  TargetResetInit                 ;目標板基本初始化
    IMPORT  StackUsr
    IMPORT  bottom_of_heap
    IMPORT  SoftwareInterrupt

;給外部使用的標號在這聲明
    EXPORT  Reset
    EXPORT  __rt_div0
    EXPORT  __user_initial_stackheap

IMPORT

此僞指令指示編譯器當前的符號不是在本源文件中定義的,而是其餘源文件中定義的,在本源文件中可能引用該符號。fetch

EXPORTthis

聲明一個符號能夠被其餘文件中引用,至關於聲明瞭一個全局變量。加密


接下來就是ARM首先執行的代碼了.spa

CODE32

    AREA    vectors,CODE,READONLY
        ENTRY
;中斷向量表
Reset
        LDR     PC, ResetAddr
        LDR     PC, UndefinedAddr
        LDR     PC, SWI_Addr
        LDR     PC, PrefetchAddr
        LDR     PC, DataAbortAddr
        DCD     0xb9205f80
        LDR     PC, [PC, #-0xff0]
        LDR     PC, FIQ_Addr

ResetAddr           DCD     ResetInit
UndefinedAddr       DCD     Undefined
SWI_Addr            DCD     SoftwareInterrupt
PrefetchAddr        DCD     PrefetchAbort
DataAbortAddr       DCD     DataAbort
Nouse               DCD     0
IRQ_Addr            DCD     0
FIQ_Addr            DCD     FIQ_Handler

C ODE32僞指令指示彙編編譯器後面的指令爲32位的ARM指令。

AREA僞指令用於定義一個代碼段和數據段。這是由於ARM彙編程序設計採用分段式設計,一個ARM源程序至少須要一個代碼段,大的程序能夠包含多個代碼段及數據段。設計

CODE和READONLY代表下面的爲代碼段且只讀。code

LDR爲大範圍的地址讀取僞指令。LDR僞指令用於加載32位的當即數或一個地址值到指定寄存器。內存

DCD用於分配一段字內存單元,並用僞指令中的expr初始化。DCD僞指令分配的內存須要字對齊,通常可用來定義數據表格或其餘常數。get

看完上面的代碼後,我有幾個疑問。

疑問1:既然是加載異常地址到PC,爲何不一下就把地址值賦給PC,而非要先LDR後DCD呢。

搜索資料後得出答案:

由於LDR指令只能跳轉到當前PC 4KB範圍內,而B指令能跳轉到32M範圍,像上面所寫LDR PC,"XXXX"這條指令不遠處用「XXXX」DCD定義一個字,而這個字裏存放最終異常服務程序的地址,這樣能夠實現4GB範圍跳轉。而LDR僞指令經過設置指令緩衝池才能實現全範圍跳轉。

疑問2:

DCD     0xb9205f80

這句話忽然出如今這裏是什麼意思?

答案:是爲了讓異常響亮跳轉那8句機器碼和爲0.爲何這樣,暫時不知道。

接下來是一些異常的處理

;未定義指令
Undefined
        B       Undefined

;取指令停止
PrefetchAbort
        B       PrefetchAbort

;取數據停止
DataAbort
        B       DataAbort

;快速中斷
FIQ_Handler
        STMFD   SP!, {R0-R3, LR}
        BL      FIQ_Exception
        LDMFD   SP!, {R0-R3, LR}
        SUBS    PC,  LR,  #4

未定義指令,取指令停止與取數據停止的處理都只是一個重複的跳轉。

接着是初始化堆棧,這是MCU復位後首先進行的工做。

InitStack    
        MOV     R0, LR

;設置中斷模式堆棧
        MSR     CPSR_c, #0xd2
        LDR     SP, StackIrq
;設置快速中斷模式堆棧
        MSR     CPSR_c, #0xd1
        LDR     SP, StackFiq
;設置停止模式堆棧
        MSR     CPSR_c, #0xd7
        LDR     SP, StackAbt
;設置未定義模式堆棧
        MSR     CPSR_c, #0xdb
        LDR     SP, StackUnd
;設置系統模式堆棧
        MSR     CPSR_c, #0xdf
        LDR     SP, =StackUsr

        MOV     PC, R0

接着是復位初始化所作的工做,其中有個工做就是上面剛剛那段代碼敘述的那樣。

ResetInit       
        BL      InitStack               ;初始化堆棧
        BL      TargetResetInit         ;目標板基本初始化
                                        
        B       __main			;跳轉到c語言入口

接着是庫函數初始化堆和棧,不能刪除。不清楚這個是什麼。

__user_initial_stackheap    
    LDR   r0,=bottom_of_heap
    MOV   pc,lr

接着是整數除法除數爲0錯誤處理代碼。上次有個同窗就是由於程序中有運算表達式中除數爲0,因此執行了下面的語句。

__rt_div0

        B       __rt_div0

接着是一些跟堆棧有關的東西,暫時不清楚是做用

StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4

而後是一個芯片加密的處理,也是暫時不知道是怎麼進行加密處理的。

IF :DEF: EN_CRP
        IF  . >= 0x1fc
        INFO    1,"\nThe data at 0x000001fc must be 0x87654321.\nPlease delete some source before this line."
        ENDIF
CrpData
    WHILE . < 0x1fc
    NOP
    WEND
CrpData1
    DCD     0x87654321          ;/* 當此數爲0x87654321時,用戶程序被保護 */

最後是分配堆棧空間,啓動文件結束。

;/* 分配堆棧空間 */
        AREA    MyStacks, DATA, NOINIT, ALIGN=2
IrqStackSpace           SPACE   IRQ_STACK_LEGTH * 4  ;中斷模式堆棧空間
FiqStackSpace           SPACE   FIQ_STACK_LEGTH * 4  ;快速中斷模式堆棧空間
AbtStackSpace           SPACE   ABT_STACK_LEGTH * 4  ;停止義模式堆棧空間
UndtStackSpace          SPACE   UND_STACK_LEGTH * 4  ;未定義模式堆棧
    END
相關文章
相關標籤/搜索