|
看了看关于IAR FOR ARM的相关资料,了解到ARM的启动在IAR中是从.s79这个文件开始的。
先来看看IAR给的列子中9200的.s79文件吧:
;-----------------------------------------------------------------------------
; This file contains the startup code used by the ICCARM C compiler.
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; All code in the modules (except ?RESET) will be placed in the ICODE segment.
;
; $Revision: 1.2 $
;
;-----------------------------------------------------------------------------
;
; Naming covention of labels in this
;
; ?xxx - External labels only accessed from assembler.
; __xxx - External labels accessed from or defined in C.
; xxx - Labels local to one module (note: this file contains
; several modules).
; main - The starting point of the user program.
;
;---------------------------------------------------------------
; Macros and definitions for the whole file
;---------------------------------------------------------------
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
;---------------------------------------------------------------
; ?RESET
; Reset Vector.
; Normally, segment INTVEC is linked at address 0.
; For debugging purposes, INTVEC may be placed at other
; addresses.
; A debugger that honors the entry point will start the
; program in a normal way even if INTVEC is not at address 0.
;---------------------------------------------------------------
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; Always ARM mode after reset //将CODE32指令之后的代码执行为32位的ARM指令
org 0x00
__program_start
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
; b ?cstartup ; Relative branch allows remap, limited to 32 MByte
; Vectors can be enabled by removing the comments below or by
; using #pragma vector from C code.
org 0x04
; ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
; ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
; ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr PC,[PC,#-0xF20]
org 0x1c
; ldr pc,[pc,#24] ; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20
dc32 ?cstartup
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif
; Add more initialization here
; Continue to ?main for more IAR specific system startup
ldr r0,=?main
bx r0
LTORG
ENDMOD
END
好长,一点一点的来啃吧。。。
抛开注释,有意义的代码是从:
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
开始的。。。
CPSR是什么?
CPSR:程序状态寄存器(current program status register) cpsr在用户级编程时用于存储条件码
CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。
以上内容详见百度百科或DATASHEET。
也就是说上面这段是用来定义这个CPSR的模式的。其中的MODE_BITS 是IAR加的(个人看法),从后面可以看出它是用来清除CPSR模式的。
接下来:
MODULE ?RESET //定义模块名称为?RESET
COMMON INTVEC:CODE:NOROOT(2) //以下代码放到INTVEC段,代码类型CODE,对齐4字节
//NOROOT表示如果这个段里的标号没引用就被linker舍弃,ROOT则一定不舍弃
//(2)表示字节对齐数,为2的幂,(2)表示4字节对齐,(3)表示8字节对齐
/****************************************************************************************************************************/
什么是对齐,以及为什么要对齐:
1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
2. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。
/****************************************************************************************************************************/
PUBLIC __program_start //公共标号
EXTERN ?cstartup //外部标号
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; Always ARM mode after reset
org 0x00 //定义下一句代码的位置。
/***********************************************************************************/
关于org指令
org指令是一条伪指令
org 会在编译期影响到内存寻址指令的编译(编译器会把所有程序用到的段内偏移地址自动加上org 后跟的数值),而其自身
并不会被编译成机器码。就是为程序中所有的引用地址(需要计算的相对地址)增加一个段内偏移值。org 指令本身并不能决定程
序将要加载到内存的什么位置,它只是告诉编译器,我的程序在编译好后需要加载到xxx 地址,所以请你在编译时帮我调整好数
据访问时的地址。
如果没有org指令,那么编译器计算偏移量(虽然nasm中没有offset但编译器仍会进行这个运算)是从0000开始的,如果有了org
,就会在最后加上org后面跟的数字。
/***********************************************************************************/
__program_start
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
//pc即程序计数器(R15)
//通过直接向PC寄存器写入目标地址可以实现在4GB的地址空间中任意跳转
//由于ARM的流水线机制,指令读取的R15的值是当前正在执行的指令地址加上8个字节
//即此处执行后R15的值为24+8=32=0x20. 程序跳转到0x20处执行
; b ?cstartup ; Relative branch allows remap, limited to 32 MByte
; Vectors can be enabled by removing the comments below or by
; using #pragma vector from C code.
org 0x04
; ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
; ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
; ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr PC,[PC,#-0xF20]
org 0x1c
; ldr pc,[pc,#24] ; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20 //由上面org的说明可知,下面代码被放到了0x20处
dc32 ?cstartup//所以,这里定义的32位常量?cstartup,也就被放到了0x20处,
//即在此定义了程序的入口
//这里由于下面的一系列org所以最后程序是从0x3c开始的.
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
快啃完了,还有1/3,加油...
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2) //SEG是重新定义段地址 RSEG---再定位段选择指令再定位段选择指令为RSEG,
//于选择一个已在前面定义过的再定位段作为当前段。
//格式: RSEG 段名段名必须是在前面已经声明过的再定位段。
//初始定义在.XCL文件中
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value 将cpsr中的值放入r0
bic r0,r0,#MODE_BITS ; Clear the mode bits 清除模式位
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits 置入IRQ模式位
msr cpsr_c,r0 ; Change the mode将r0中的值放到cpsr_c 这个时候模式就已 ; 经转换为irq模式了,每一个模式都有自己的 sp.
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK 这里的SFE 是iar内置函数目的是取到这 ;个段的地址。&0xFFFFFFF8是为了数据对齐。ldr 指令是要 ;求32位对齐的。
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif
; Add more initialization here
; Continue to ?main for more IAR specific system startup
ldr r0,=?main //在这里跳转到 main 函数的开始。
//OK!我们终于可以去main函数啦
bx r0
LTORG
ENDMOD
END
看了看关于IAR FOR ARM的相关资料,了解到ARM的启动在IAR中是从.s79这个文件开始的。
先来看看IAR给的列子中9200的.s79文件吧:
;-----------------------------------------------------------------------------
; This file contains the startup code used by the ICCARM C compiler.
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; All code in the modules (except ?RESET) will be placed in the ICODE segment.
;
; $Revision: 1.2 $
;
;-----------------------------------------------------------------------------
;
; Naming covention of labels in this
;
; ?xxx - External labels only accessed from assembler.
; __xxx - External labels accessed from or defined in C.
; xxx - Labels local to one module (note: this file contains
; several modules).
; main - The starting point of the user program.
;
;---------------------------------------------------------------
; Macros and definitions for the whole file
;---------------------------------------------------------------
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
;---------------------------------------------------------------
; ?RESET
; Reset Vector.
; Normally, segment INTVEC is linked at address 0.
; For debugging purposes, INTVEC may be placed at other
; addresses.
; A debugger that honors the entry point will start the
; program in a normal way even if INTVEC is not at address 0.
;---------------------------------------------------------------
MODULE ?RESET
COMMON INTVEC:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; Always ARM mode after reset //将CODE32指令之后的代码执行为32位的ARM指令
org 0x00
__program_start
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
; b ?cstartup ; Relative branch allows remap, limited to 32 MByte
; Vectors can be enabled by removing the comments below or by
; using #pragma vector from C code.
org 0x04
; ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
; ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
; ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr PC,[PC,#-0xF20]
org 0x1c
; ldr pc,[pc,#24] ; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20
dc32 ?cstartup
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif
; Add more initialization here
; Continue to ?main for more IAR specific system startup
ldr r0,=?main
bx r0
LTORG
ENDMOD
END
好长,一点一点的来啃吧。。。
抛开注释,有意义的代码是从:
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR
USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode
开始的。。。
CPSR是什么?
CPSR:程序状态寄存器(current program status register) cpsr在用户级编程时用于存储条件码
CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。
以上内容详见百度百科或DATASHEET。
也就是说上面这段是用来定义这个CPSR的模式的。其中的MODE_BITS 是IAR加的(个人看法),从后面可以看出它是用来清除CPSR模式的。
接下来:
MODULE ?RESET //定义模块名称为?RESET
COMMON INTVEC:CODE:NOROOT(2) //以下代码放到INTVEC段,代码类型CODE,对齐4字节
//NOROOT表示如果这个段里的标号没引用就被linker舍弃,ROOT则一定不舍弃
//(2)表示字节对齐数,为2的幂,(2)表示4字节对齐,(3)表示8字节对齐
/****************************************************************************************************************************/
什么是对齐,以及为什么要对齐:
1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
2. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。
/****************************************************************************************************************************/
PUBLIC __program_start //公共标号
EXTERN ?cstartup //外部标号
EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
CODE32 ; Always ARM mode after reset
org 0x00 //定义下一句代码的位置。
/***********************************************************************************/
关于org指令
org指令是一条伪指令
org 会在编译期影响到内存寻址指令的编译(编译器会把所有程序用到的段内偏移地址自动加上org 后跟的数值),而其自身
并不会被编译成机器码。就是为程序中所有的引用地址(需要计算的相对地址)增加一个段内偏移值。org 指令本身并不能决定程
序将要加载到内存的什么位置,它只是告诉编译器,我的程序在编译好后需要加载到xxx 地址,所以请你在编译时帮我调整好数
据访问时的地址。
如果没有org指令,那么编译器计算偏移量(虽然nasm中没有offset但编译器仍会进行这个运算)是从0000开始的,如果有了org
,就会在最后加上org后面跟的数字。
/***********************************************************************************/
__program_start
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
//pc即程序计数器(R15)
//通过直接向PC寄存器写入目标地址可以实现在4GB的地址空间中任意跳转
//由于ARM的流水线机制,指令读取的R15的值是当前正在执行的指令地址加上8个字节
//即此处执行后R15的值为24+8=32=0x20. 程序跳转到0x20处执行
; b ?cstartup ; Relative branch allows remap, limited to 32 MByte
; Vectors can be enabled by removing the comments below or by
; using #pragma vector from C code.
org 0x04
; ldr pc,[pc,#24] ; Branch to undef_handler
org 0x08
; ldr pc,[pc,#24] ; Branch to swi_handler
org 0x0c
; ldr pc,[pc,#24] ; Branch to prefetch_handler
org 0x10
; ldr pc,[pc,#24] ; Branch to data_handler
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr PC,[PC,#-0xF20]
org 0x1c
; ldr pc,[pc,#24] ; Branch to fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
; Exception vectors can be specified in C code by #pragma vector or by filling
; in the vectors below. The vector address is the ARM vector number + 0x20.
org 0x20 //由上面org的说明可知,下面代码被放到了0x20处
dc32 ?cstartup//所以,这里定义的32位常量?cstartup,也就被放到了0x20处,
//即在此定义了程序的入口
//这里由于下面的一系列org所以最后程序是从0x3c开始的.
org 0x24
; dc32 undef_handler
org 0x28
; dc32 swi_handler
org 0x2c
; dc32 prefetch_handler
org 0x30
; dc32 data_handler
org 0x38
; dc32 irq_handler
org 0x3c
; dc32 fiq_handler
LTORG
; ENDMOD __program_start
ENDMOD
快啃完了,还有1/3,加油...
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2) //SEG是重新定义段地址 RSEG---再定位段选择指令再定位段选择指令为RSEG,
//于选择一个已在前面定义过的再定位段作为当前段。
//格式: RSEG 段名段名必须是在前面已经声明过的再定位段。
//初始定义在.XCL文件中
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value 将cpsr中的值放入r0
bic r0,r0,#MODE_BITS ; Clear the mode bits 清除模式位
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits 置入IRQ模式位
msr cpsr_c,r0 ; Change the mode将r0中的值放到cpsr_c 这个时候模式就已 ; 经转换为irq模式了,每一个模式都有自己的 sp.
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK 这里的SFE 是iar内置函数目的是取到这 ;个段的地址。&0xFFFFFFF8是为了数据对齐。ldr 指令是要 ;求32位对齐的。
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif
; Add more initialization here
; Continue to ?main for more IAR specific system startup
ldr r0,=?main //在这里跳转到 main 函数的开始。
//OK!我们终于可以去main函数啦
bx r0
LTORG
ENDMOD
END