初始化程序中必须指明入口地址,因为处理器复位(仿真时,装载image)后PC 要找到入口开始执行代码,当各种异常或是中断产生的时候也要找到各个异常的入口开始执行代
码。从这里开始就是真正的代码入口了!
AREA 伪指令用于定义一个代码段或数据段.ARM 汇编程序设计采用分段式设计,一
个 ARM 源程序至少需要一个代码段,大的程序可以包含多少个代码段及数据段.
CODE 为定义代码段.默认属性为 READONLY;
READONLY 指定本段为只读,代码段的默认属性为READONLY;
;==========================================================
;板子上电和复位后程序开始从位于0x0处开始执行,硬件刚刚上电复位后程序从这里开始执行跳转到标为ResetHandler处执行
;DCD用于分配一段字内存单片,并用后面的伪指令初始化,分配字节由expr 个数决定
AREA Init,CODE,READONLY;声明一个名为Init的代码段, ;Init 初始化程序
ENTRY 程序的入口点,(调试用)
;ENTRY只是定义一个普通的入口点,且在程序中可以多处定义,如果要使用它作为整
个映像文件的唯一入口点,还需要设置链接器中的相关选项。
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断言错误伪指令,这里表示是否定义过ENDIAN_CHANGE
[ ENDIAN_CHANGE ;如果定义了ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH ;这里表示是否定义过ENTRY_BUS_WIDTH
;如果没有定义ENTRY_BUS_WIDTH就报错
[ ENTRY_BUS_WIDTH=32 ;if ENTRY_BUS_WIDTH=32
b ChangeBigEndian ;跳转到ChangeBigEndian (见下面红色代码),执行DCD 0xea000007 改变大小端数据模式
] ;end if
[ ENTRY_BUS_WIDTH=16 ;if ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;当标志状态寄存器CPSR的Z位=1时,r14=r7+r0逻辑左移20位,执行DCD 0x0007ea00改变大小端模式
] ;end if
[ ENTRY_BUS_WIDTH=8 ;if ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ; 当标志状态寄存器CPSR的Z位=1时…,执行DCD 0x070000ea 改变大小端模式
]
| ;ELSE 即如果没定义ENDIAN_CHANGE
b ResetHandler;复位异常,开发板上电或复位时进入0x00
]
中断向量表一般位于启动代码的开始部分,它是用户程序与启动代码之间以及启动代码
的各部分之间联系的纽带。它由一个一个的跳转函数组成,它就象一个普通的散转函数,只
不过散转的过程中有硬件机制参与,当系统发生异常时,ARM 处理器会通过硬件机制强制
将PC 指针指向中断向量表中对应的异常跳转函数存储的地址,然后程序会跳转到相应的中
断服务程序去执行。
b HandlerUndef ;handler for Undefined mode 未定义异常,遇到无法识别的指令时0x04
b HandlerSWI ;handler for SWI interrupt,软中断异常0x08
b HandlerPabort ;handler for PAbort指令预取错误时进入0x0c 处理终止程序访问终止模式
b HandlerDabort ;handler for DAbort数据访问不能完成时进入0x10 处理数据访问终止模式
b . ;reserved, 保留 0x14 "."代表指令的地址 ,即表示进行死循环
b HandlerIRQ ;handler for IRQ interrupt发生IRQ 中断时进入0x18
b HandlerFIQ ;handler for FIQ interrupt发生FIQ 中断时进入0x1c
;@0x20 "@" 存储区位置计数器的当前值
b EnterPWDN ; Must be @0x20.
158 ;===============================================================
159 ;下面是改变大小端的程序,这里采用直接定义机器码的方式,至于说为什么这么做
160 ;就得问三星了反正我们程序里这段代码也不会去执行,不用去管它
161 ;===============================================================
ChangeBigEndian ;改变大小端数据模式
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD用于分配一段字内存单元,并用伪指令中的expr初始化.DCD伪指令分配的内存
需要字对齐,一般可用来定义数据表格或其它常数.&与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