寒江月刃的笔记 https://bbs.21ic.com/?605891 [收藏] [复制] [RSS]

日志

关于IAR的.s79文件

已有 1963 次阅读2010-2-4 15:16 |系统分类:ARM

看了看关于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


路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新日志

评论 (0 个评论)