初始化程序中必須指明入口地址,因為處理器復位(仿真時(shí),裝載image)后PC 要找到入口開(kāi)始執行代碼,當各種異?;蚴侵袛喈a(chǎn)生的時(shí)候也要找到各個(gè)異常的入口開(kāi)始執行代碼。從這里開(kāi)始就是真正的代碼入口了!
本文引用地址:http://dyxdggzs.com/article/201611/319023.htm
AREA 偽指令用于定義一個(gè)代碼段或數據段.ARM 匯編程序設計采用分段式設計,一
個(gè) ARM 源程序至少需要一個(gè)代碼段,大的程序可以包含多少個(gè)代碼段及數據段.
CODE 為定義代碼段.默認屬性為 READONLY;
READONLY 指定本段為只讀,代碼段的默認屬性為READONLY;
;==========================================================
;板子上電和復位后程序開(kāi)始從位于0x0處開(kāi)始執行,硬件剛剛上電復位后程序從這里開(kāi)始執行跳轉到標為ResetHandler處執行
;DCD用于分配一段字內存單片,并用后面的偽指令初始化,分配字節由expr 個(gè)數決定
AREA Init,CODE,READONLY;聲明一個(gè)名為Init的代碼段, ;Init 初始化程序
ENTRY 程序的入口點(diǎn),(調試用)
;ENTRY只是定義一個(gè)普通的入口點(diǎn),且在程序中可以多處定義,如果要使用它作為整
個(gè)映像文件的唯一入口點(diǎn),還需要設置鏈接器中的相關(guān)選項。
EXPORT __ENTRY
__ENTRY
ResetEntry ;復位后的入口
;1)The code, which converts to Big-endian, should be in little endian code.
;2)The following little endian code will be compiled in Big-Endian mode.
; The code byte order should be changed as the memory bus width.
;3)The pseudo instruction,DCD can not be used here because the linker generates error.
ASSERT :DEF:ENDIAN_CHANGE
;ASSERT斷言錯誤偽指令,這里表示是否定義過(guò)ENDIAN_CHANGE
[ ENDIAN_CHANGE ;如果定義了ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH ;這里表示是否定義過(guò)ENTRY_BUS_WIDTH
;如果沒(méi)有定義ENTRY_BUS_WIDTH就報錯
[ ENTRY_BUS_WIDTH=32 ;if ENTRY_BUS_WIDTH=32
b ChangeBigEndian ;跳轉到ChangeBigEndian (見(jiàn)下面紅色代碼),執行DCD 0xea000007 改變大小端數據模式
] ;end if
[ ENTRY_BUS_WIDTH=16 ;if ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;當標志狀態(tài)寄存器CPSR的Z位=1時(shí),r14=r7+r0邏輯左移20位,執行DCD 0x0007ea00改變大小端模式
] ;end if
[ ENTRY_BUS_WIDTH=8 ;if ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ; 當標志狀態(tài)寄存器CPSR的Z位=1時(shí)…,執行DCD 0x070000ea 改變大小端模式
]
| ;ELSE 即如果沒(méi)定義ENDIAN_CHANGE
b ResetHandler;復位異常,開(kāi)發(fā)板上電或復位時(shí)進(jìn)入0x00
]
中斷向量表一般位于啟動(dòng)代碼的開(kāi)始部分,它是用戶(hù)程序與啟動(dòng)代碼之間以及啟動(dòng)代碼
的各部分之間聯(lián)系的紐帶。它由一個(gè)一個(gè)的跳轉函數組成,它就象一個(gè)普通的散轉函數,只
不過(guò)散轉的過(guò)程中有硬件機制參與,當系統發(fā)生異常時(shí),ARM 處理器會(huì )通過(guò)硬件機制強制
將PC 指針指向中斷向量表中對應的異常跳轉函數存儲的地址,然后程序會(huì )跳轉到相應的中
斷服務(wù)程序去執行。
b HandlerUndef ;handler for Undefined mode 未定義異常,遇到無(wú)法識別的指令時(shí)0x04
b HandlerSWI ;handler for SWI interrupt,軟中斷異常0x08
b HandlerPabort ;handler for PAbort指令預取錯誤時(shí)進(jìn)入0x0c 處理終止程序訪(fǎng)問(wèn)終止模式
b HandlerDabort ;handler for DAbort數據訪(fǎng)問(wèn)不能完成時(shí)進(jìn)入0x10 處理數據訪(fǎng)問(wèn)終止模式
b . ;reserved, 保留 0x14 "."代表指令的地址 ,即表示進(jìn)行死循環(huán)
b HandlerIRQ ;handler for IRQ interrupt發(fā)生IRQ 中斷時(shí)進(jìn)入0x18
b HandlerFIQ ;handler for FIQ interrupt發(fā)生FIQ 中斷時(shí)進(jìn)入0x1c
;@0x20 "@" 存儲區位置計數器的當前值
b EnterPWDN ; Must be @0x20.
158 ;===============================================================
159 ;下面是改變大小端的程序,這里采用直接定義機器碼的方式,至于說(shuō)為什么這么做
160 ;就得問(wèn)三星了反正我們程序里這段代碼也不會(huì )去執行,不用去管它
161 ;===============================================================
ChangeBigEndian ;改變大小端數據模式
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD用于分配一段字內存單元,并用偽指令中的expr初始化.DCD偽指令分配的內存
需要字對齊,一般可用來(lái)定義數據表格或其它常數.&與DCD 同義.
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler ;復位處理程式
;進(jìn)入掉電模式功能
; 1. SDRAM 必須在自刷新模式.
; 2. 所有中斷必須屏蔽 for SDRAM/DRAM self-refresh.
; 3. LCD 關(guān)閉for SDRAM/DRAM self-refresh.
; 4. The I-cache 可能需要開(kāi)啟.
; 5. The location of the following code may have not to be changed.
;如第前面所說(shuō),這里采用HANDLER宏去建立Hander***和Handle***之間的聯(lián)系
HandlerFIQ HANDLER HandleFIQ ;HandlerIRQ 行號 HANDLER 宏名 HandleIRQ 導入的形參
Ha ndlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
評論