📄 boot.s
字号:
;/*
;************************************************************************************************************
;** boot.s **
;************************************************************************************************************
;*/
IMPORT |Image$$RO$$Base| ;// 声明输入ROM区中的RO的开始地址
IMPORT |Image$$RO$$Limit| ;// 声明输入ROM区中的RW地址(即:存储RO代码最后地址的下一地址)
IMPORT |Image$$RW$$Base| ;// 声明输入RAM区的开始地址
IMPORT |Image$$RW$$Limit| ;// 声明输入零初始化区的开始地址(即:RAM区的最后地址的下一地址)
IMPORT |Image$$ZI$$Base| ;// 声明输入零初始化区的开始地址
IMPORT |Image$$ZI$$Limit| ;// 声明输入零初始化区的末地址的下一地址
IMPORT main ;// 声明输入主程序入口地址
EWRAM_START EQU 0x02000000 ;// CPU外部工作RAM
EWRAM_END EQU 0x02040000-1 ;// (256 Kbytes)
EWRAM_LEN EQU EWRAM_END - EWRAM_START+1
IWRAM_START EQU 0x03000000 ;// CPU内部工作RAM(32K)用于储存程序和数据
IWRAM_END EQU 0x03008000-1 ;// (32 Kbytes)
IWRAM_LEN EQU IWRAM_END - IWRAM_START + 1
EWROM_START EQU 0x08000000 ;// 卡带记忆体开始地址
ARM_USR_SP EQU 0x03007F00 ;// 用户堆栈起始地址
ARM_IRQ_SP EQU 0x03007FA0 ;// 普通中断堆栈起始地址
ARM_SVC_SP EQU 0x03007FE0 ;// 系统调用堆栈起始地址
INTR_VECTOR_ADDR EQU 0x3008000 - 4 ;// 中断向量地址 0x3007ffc
;//模式定义
ARM_USE_MODE EQU 0X10
ARM_FIQ_MODE EQU 0X11
ARM_IRQ_MODE EQU 0X12
ARM_SVC_MODE EQU 0X13
ARM_ABORT_MODE EQU 0X17
ARM_UNDEF_MODE EQU 0X1B
ARM_SYS_MODE EQU 0X1F
ARM_NOINT EQU 0XC0
;/*
;************************************************************************************************************
;** 程序开始 **
;************************************************************************************************************
;*/
CODE32
AREA INIT, CODE, READONLY
ENTRY ;// 入口
_start ;// 入口
b rom_header_end ;// 跳过程序区域驻留的一些关于游戏的信息
Nintendo_Logo
SPACE 156 ;// 任天堂图标字符数据 (8000004h)
;// 游戏标题(80000A0h)
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00
;// 游戏代码 (80000ACh)
;// 无则全0
DCB "MB "
;// 制造商代码 (80000B0h)
DCB 0x30,0x31
;// 固定值 (80000B2h)
DCB 0x96
;// 主单元代码:
;// 储存可运行软件的硬件代码。 (80000B3h)
DCB 0x00
;// 设备类型 (80000B4h)
DCB 0x00
;//未使用(固定)的数据 (7Byte) (80000B5h)
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00
;// 软件版本号:
;// 储存ROM版本号 (80000BCh)
DCB 0x00
;// 补码检查 (80000BDh)
DCB 0xf0
;// 校验和(80000BEh)
DCB 0x00,0x00
rom_header_end
b start_vector ;// 这个标号在这里是适当的
;// 作为下面的开始地址
;// 不要删除它
;/**********************************************************************
;======================================================================+
;
; The following reserved bytes are used if the code is compiled for
; multiboot mode. It does not hurt anything to leave this header in
; even if the code is not compiled for multiboot. The GBA BIOS will
; auto-patch the first two bytes with 0x03 and 0x01, respectively,
; before running any code if it is executed as multiboot.
;
; The following two bytes are included even for non-multiboot supporting
; builds to guarantee that any generic library code that depends on them
; will still be functional.
;======================================================================+
;***********************************************************************/
EXPORT BOOT_METHOD , SLAVE_NUMBER
BOOT_METHOD
DCB 0 ;// boot method (0=ROM boot, 3=Multiplay boot)
SLAVE_NUMBER
DCB 0 ;// slave # (1=slave#1, 2=slave#2, 3=slave#3)
DCB 0 ; reserved
DCB 0 ; reserved
DCD 0 ; reserved
DCD 0 ; reserved
DCD 0 ; reserved
DCD 0 ; reserved
DCD 0 ; reserved
DCD 0 ; reserved
;//---------end--------------------------------------------------------+
;/*
;************************************************************************************************************
;** 复位 **
;************************************************************************************************************
;*/
EXPORT start_vector ;//输出复位
EXTERN intr_main ;//声名输入intr_main
ALIGN
start_vector
;/*
;************************************************************************************************************
;** 堆栈初始化 **
;************************************************************************************************************
;*/
mov r0, #ARM_IRQ_MODE:OR:0x80:OR:0x40 ;// 关中断
msr CPSR_c, r0 ;// 进入IRQ模式
ldr r13, =ARM_IRQ_SP ;// 初始化IRQ模式堆栈指针
mov r0, #ARM_SVC_MODE:OR:0x80:OR:0x40 ;// 关中断
msr CPSR_c, r0 ;// 进入SVC模式
ldr r13, =ARM_SVC_SP ;// 初始化SVC模式堆栈指针
;/*
;************************************************************************************************************
;** 初始化应用程序执行环境 **
;************************************************************************************************************
;*/
;//确保CPU运行在外部工作RAM
mov r0,pc ;// 查询一下现运行在哪个空间
cmp r0,#EWROM_START ;// 是小于 0x08000000 ?
bls SkipEWRAMClear ;// 如果小于, 已运行在外部工作RAM
;// 如果高于, 运行在 pak ,所以我们需要复制.
;//复制代码到外部工作RAM
ldr r3,=EWRAM_LEN
ldr r2,=EWRAM_START
mov r6,r2
ldr r1,=EWROM_START
bl CopyMem ;//调用 CopyMem
;//跳转到外部工作RAM执行
bx r6
SkipEWRAMClear
ldr r0, =|Image$$RO$$Limit| ;//输入ROM区中的RW地址(即:存储RO代码最后地址的下一地址)
ldr r1, =|Image$$RW$$Base| ;//RAM区的开始地址
ldr r3, =|Image$$ZI$$Base| ;//零初始化区的开始地址
cmp r0, r1 ;//比较地址是否相同?
beq %F1
0 cmp r1, r3 ;//复制初始化数据
ldrcc r2, [r0], #4 ;//把ROM区中的RW地址中的数据放入寄存器
strcc r2, [r1], #4 ;//把寄存器中的数据放入RAM区中,放完后,刚好到达ZI区的首地址
bcc %B0
1 ldr r1, =|Image$$ZI$$Limit| ;//零初始化区的末地址的下一地址
mov r2, #0
2 cmp r3, r1 ;//对零初始化区进行零初始化
strcc r2, [r3], #4
bcc %B2
ldr r1, =INTR_VECTOR_ADDR ;//设置中断地址
ldr r0, =intr_main
str r0, [r1]
mov r0, #ARM_SVC_MODE:OR:0x40 ;//使能IRQ中断
msr CPSR_c, r0
mov r0, #ARM_USE_MODE:OR:0x40 ;//使能IRQ中断
msr CPSR_c, r0 ;//进入USE模式
ldr sp, =ARM_USR_SP ;//设置USE模式堆栈指针
;/*
;************************************************************************************************************
;** 呼叫主应用程序 **
;************************************************************************************************************
;*/
bl main ;//进入C代码
;/*
;************************************************************************************************************
;** 内存操作 **
;************************************************************************************************************
;*/
;/**************************************
;--------ClearMem----------------------+
; 内存清零 |
; r0 = 起始地址 |
; r1 = 长度 |
;--------------------------------------+
;**************************************/
ClearMem
mov r2,#3 ;//确保长度是4的倍数
add r1,r1,r2
bic r1,r1,r2
mov r2,#0
cmp r1,r2
beq ClearMX ;//长度为0退出
ClrLoop
stmia r0!,{r2}
sub r1,r1,#4
cmp r1,#0
bne ClrLoop
ClearMX
bx lr ;// ret
;//---------end of ClearMem------------
;/**************************************
;---------- Copy memory --------------+
; 内存复制 |
; r1 = 源地址 |
; r2 = 目标地址 |
; r3 = 长度 |
;-------------------------------------+
;**************************************/
CopyMem
mov r0,#3 ;//确保长度是4的倍数
add r3,r3,r0
bic r3,r3,r0
beq CIDExit ;//长度为0退出
CIDLoop
ldmia r1!,{r0}
stmia r2!,{r0}
sub r3,r3,#4
cmp r3,#0
bne CIDLoop
CIDExit
bx lr ;// ret
;//--------- end of CopyMem ------------------
END ;//结束boot.s
;/*
;************************************************************************************************************
;** 结束 **
;************************************************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -