GD32 starup_gd32e10x.s分析


;/*!
;    \file    startup_gd32e10x.s
;    \brief   start up file
;
;    \version 2017-12-26, V1.0.0, firmware for GD32E10x
;*/
;
;/*
;    Copyright (c) 2017, GigaDevice Semiconductor Inc.
;
;    All rights reserved.
;
;    Redistribution and use in source and binary forms, with or without modification, 
;are permitted provided that the following conditions are met:
;
;    1. Redistributions of source code must retain the above copyright notice, this 
;       list of conditions and the following disclaimer.
;    2. Redistributions in binary form must reproduce the above copyright notice, 
;       this list of conditions and the following disclaimer in the documentation 
;       and/or other materials provided with the distribution.
;    3. Neither the name of the copyright holder nor the names of its contributors 
;       may be used to endorse or promote products derived from this software without 
;       specific prior written permission.
;
;    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
;OF SUCH DAMAGE.
;*/

; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
; 定义栈的大小
Stack_Size      EQU     0x00000400
;定义名字为STACK的独立区域,其实就是栈区,栈区没有初始化,可读可写,并且以2^3=8字节对齐
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
;申请了Stack_Size的空间,也就是0x400 大概 1024的栈空间。(SPACE申请一片内存空间但是不赋值)                
Stack_Mem       SPACE   Stack_Size
;这里的__initial_sp定了一个标签(label),代码当前指令的地址,后面会用DCD赋值,但是赋值什么呢?
;初始化栈顶指针,指向堆栈顶,因为栈是向下增长的,所以栈顶在最下面,堆是向上增长的,所以这里也是堆顶?
__initial_sp


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
;定义堆的大小
Heap_Size       EQU     0x00000400

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
;定义_heap_base标签,后面会赋值?                
__heap_base
Heap_Mem        SPACE   Heap_Size
;定义__heap_limit标签,后面会赋值?
__heap_limit
;Preserve意思是保留维持,这里的PRESERVE8是字节对齐的关键字,指定当前文件保持堆栈8字节对齐
                PRESERVE8
; 告诉编译器使用THUMB指令集,THUMB 必须位于使用新语法的任何Thumb代码之前                                
                THUMB

;               /* reset Vector Mapped to at Address 0 */
;复位段,只包含数据,只读,没搞明白这个东西,这个确实是复位段,但是复位段有什么作用,还是只是起了名字而已
                AREA    RESET, DATA, READONLY
; EXPORT 命令声明一个符号,可由链接器用于解释各个目标和库文件中的符号引用,相当于声明了一个全局变量。 GLOBAL 于 EXPORT相同 
;为什么引号EXPORT __Vectors ???               
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
;关键字DCD代表申请一个字的空间,后面的函数名即为中断服务函数入口地址。另外中断向量表一般存放在Flash 0地址
;第一行,用DCD申请一个字的空间,然后用后面的表达式(__initial_sp,这其实是一个地址->栈顶指针)初始化
__Vectors       DCD     __initial_sp                      ; Top of Stack
;下面是Reset_Handler,复位函数,关于这两个地址,__initial_sp和Reset_Handler,程序上电后,首先加载SP和PC,
;ARM规定从0地址处加载SP,从偏移为4的地址(0x00000004)处加载PC。然后将程序控制权交给程序。我们知道0地址处存放
;__initial_sp???0x00000004地址处存放Reset_Handler,加载PC后,程序跳转到Reset_Handler开始运行。
;后面看下Reset_Handler函数
                DCD     Reset_Handler                     ; Reset Handler
                DCD     NMI_Handler                       ; NMI Handler
                DCD     HardFault_Handler                 ; Hard Fault Handler
                DCD     MemManage_Handler                 ; MPU Fault Handler
                DCD     BusFault_Handler                  ; Bus Fault Handler
                DCD     UsageFault_Handler                ; Usage Fault Handler
                DCD     0                                 ; Reserved
                DCD     0                                 ; Reserved
                DCD     0                                 ; Reserved
                DCD     0                                 ; Reserved
                DCD     SVC_Handler                       ; SVCall Handler
                DCD     DebugMon_Handler                  ; Debug Monitor Handler
                DCD     0                                 ; Reserved
 ;uC/OS-II中任务切换的时候会调用到,其中做了现场保存,并且在遇到其他中断和SysTick中断冲突时候其缓冲作用               
                DCD     PendSV_Handler                    ; PendSV Handler
 ;系统tick中断,想起来有人又疑问Systick中断和Timer中断的区别,喏,这里就是区别,SysTick中断是ARM核心内部中断,
 ;你那些Timer啥的都是外部中断,Timer当然作用更丰富一些               
                DCD     SysTick_Handler                   ; SysTick Handler

;               /* external interrupts handler */
                DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
                DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
                DCD     TAMPER_IRQHandler                 ; 18:Tamper through EXTI Line detect
                DCD     RTC_IRQHandler                    ; 19:RTC through EXTI Line
                DCD     FMC_IRQHandler                    ; 20:FMC
                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
                DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
                DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
                DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
                DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
                DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
                DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel0
                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
                DCD     ADC0_1_IRQHandler                 ; 34:ADC0 and ADC1
                DCD     CAN0_TX_IRQHandler                ; 35:CAN0 TX
                DCD     CAN0_RX0_IRQHandler               ; 36:CAN0 RX0
                DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
                DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
                DCD     EXTI5_9_IRQHandler                ; 39:EXTI5 to EXTI9
                DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8
                DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9
                DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
                DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
                DCD     TIMER1_IRQHandler                 ; 44:TIMER1
                DCD     TIMER2_IRQHandler                 ; 45:TIMER2
                DCD     TIMER3_IRQHandler                 ; 46:TIMER3
                DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
                DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
                DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
                DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
                DCD     SPI0_IRQHandler                   ; 51:SPI0
                DCD     SPI1_IRQHandler                   ; 52:SPI1
                DCD     USART0_IRQHandler                 ; 53:USART0
                DCD     USART1_IRQHandler                 ; 54:USART1
                DCD     USART2_IRQHandler                 ; 55:USART2
                DCD     EXTI10_15_IRQHandler              ; 56:EXTI10 to EXTI15
                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
                DCD     USBFS_WKUP_IRQHandler             ; 58:USBFS Wakeup
                DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break and TIMER11
                DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update and TIMER12
                DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
                DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Channel Capture Compare
                DCD     0                                 ; 63:Reserved
                DCD     EXMC_IRQHandler                   ; 64:EXMC
                DCD     0                                 ; 65:Reserved
                DCD     TIMER4_IRQHandler                 ; 66:TIMER4
                DCD     SPI2_IRQHandler                   ; 67:SPI2
                DCD     UART3_IRQHandler                  ; 68:UART3
                DCD     UART4_IRQHandler                  ; 69:UART4
                DCD     TIMER5_IRQHandler                 ; 70:TIMER5 
                DCD     TIMER6_IRQHandler                 ; 71:TIMER6
                DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
                DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
                DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
                DCD     DMA1_Channel3_IRQHandler          ; 75:DMA1 Channel3
                DCD     DMA1_Channel4_IRQHandler          ; 76:DMA1 Channel4
                DCD     0                                 ; 77:Reserved
                DCD     0                                 ; 78:Reserved
                DCD     CAN1_TX_IRQHandler                ; 79:CAN1 TX
                DCD     CAN1_RX0_IRQHandler               ; 80:CAN1 RX0
                DCD     CAN1_RX1_IRQHandler               ; 81:CAN1 RX1
                DCD     CAN1_EWMC_IRQHandler              ; 82:CAN1 EWMC
                DCD     USBFS_IRQHandler                  ; 83:USBFS
;__Vectors_End就是当前指令的地址,可以用来计算这个向量的size,当然这个size你也可以数一数有多少个DCD,然后乘以4得到
__Vectors_End
;EQU就不说了,这个理解为赋值语句就可以了,__Vectors_Size的大小
__Vectors_Size  EQU     __Vectors_End - __Vectors
;这里用AREA指示汇编程序汇编新的代码节,指定的节名是“.text",注意这里语法上如果节名中首位是数字的话必须在首尾加入'|'
;这里没有数字而是习惯性的表示节名的方法 ,表示由C编译器生成的代码节。CODE属性表示定义的是代码节,READONLY只读
                AREA    |.text|, CODE, READONLY

;/* reset Handler */
;proc是定义子程序的伪指令
Reset_Handler   PROC
;如果EXPORT带有WEAK的话,其他文件中有定义Reset_Handler有同名函数的话就用其他文件中的函数
;如果没有,则就用本地的Reset_Handler函数,这个好像是C++中的继承,不同的是,一旦其他文件中有
;同名的函数,则本地的函数就彻底无用了
                EXPORT  Reset_Handler                     [WEAK]
;IMPORT表示这是一个外部变量的标号,不是本程序中定义的 ,这两个函数都在外面有定义
;可以看出在main函数调用之前调用了systeminit
                IMPORT  SystemInit    
                IMPORT  __main
;这里说一下LDR,说的多一点,ARM是RISC(精简指令集计算机)结构,只有载入(loader)和存储(store)指令可以访问存储器,
;数据处理指令只对寄存器的内容进行操作。这里利用LDR伪指令(注意不是LDR指令)用“="表示地址,把SystemInit的地址写入到R0中
;需要把内存中的地址读到寄存器中只能使用LDR,不能用mov,mov只能在寄存器之间移动数据               
                LDR     R0, =SystemInit
;BLX 带链接和带状态切换的跳转,首先将当前指令的下一条指令地址保存在LR(R14)寄存器中,然后跳转,这体现了BLX的带链接性,
;BLX同时又是带状态切换的跳转,从BLX R0;跳转到R0中的地址(注意我说的不是R0地址),如果R0[0]=1,则进入Thumb状态
;BLX 同时兼容了BL和BX的功能,为什么这里用带链接功能的跳转呢,下面跳转到main函数的时候为什么用的BX,因为main函数后面就
;没有要执行的指令了,不必保存PC到LR中了,PC中保存的时候当前指令的下一条指令,在执行函数的时候执行完返回的时候要知道进入函数
;之前的下一条指令地址                
                BLX     R0
;下面LDR是将内存中的__main函数的地址存储到LDR中,再啰嗦一句,ARM指令集是精简指令集,从内存搬运数据到寄存器只能用load(LDR)的方法               
                LDR     R0, =__main
;BX R0,带状态切换的跳转,R0[0](R0的最低为如果是1的话)=1的话,则状态切换为Thumb状态 ,为什么切换为Thumb状态,因为Thumb是十六位指令
;AMR指令是32位指令,更低位数的指令代表更高的代码密度,更高的代码密度意味着更低的功耗,所以能用thumb的情况下就用thumb,这是我的理解,
;欢迎斧正              
                BX      R0
 ;ENDP表示这个子程序结束了,这个很容易理解。最后总结下,相当于这行了Reset_Handler之后再执行SystemInit和main               
                ENDP

;/* dummy Exception Handlers */
;EXPORT func [WEAK],其他文件中有此fun函数的话就用其他文件中的,当前文件中的fun不起作用
NMI_Handler     PROC
                EXPORT  NMI_Handler                       [WEAK]
; B . 这里有个'.'指的是当前行地址,就跳到当前行                
                B       .
                ENDP
;这里'\'用来表示换行,主要是和上面对齐用的                
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler                 [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler                 [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler                  [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler                [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                       [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler                  [WEAK]
                B       .
                ENDP
PendSV_Handler\
                PROC
                EXPORT  PendSV_Handler                    [WEAK]
                B       .
                ENDP
SysTick_Handler\
                PROC
                EXPORT  SysTick_Handler                   [WEAK]
                B       .
                ENDP
;不知道什么情况下可以调用到Default_Handler ,这个首先是个子程序,在什么情况下会调用到此函数
Default_Handler PROC
;               /* external interrupts handler */
                EXPORT  WWDGT_IRQHandler                  [WEAK]
                EXPORT  LVD_IRQHandler                    [WEAK]                  
                EXPORT  TAMPER_IRQHandler                 [WEAK]           
                EXPORT  RTC_IRQHandler                    [WEAK]               
                EXPORT  FMC_IRQHandler                    [WEAK]                
                EXPORT  RCU_CTC_IRQHandler                [WEAK]                 
                EXPORT  EXTI0_IRQHandler                  [WEAK]                  
                EXPORT  EXTI1_IRQHandler                  [WEAK]                 
                EXPORT  EXTI2_IRQHandler                  [WEAK]               
                EXPORT  EXTI3_IRQHandler                  [WEAK]                
                EXPORT  EXTI4_IRQHandler                  [WEAK]                 
                EXPORT  DMA0_Channel0_IRQHandler          [WEAK]         
                EXPORT  DMA0_Channel1_IRQHandler          [WEAK]          
                EXPORT  DMA0_Channel2_IRQHandler          [WEAK]        
                EXPORT  DMA0_Channel3_IRQHandler          [WEAK]         
                EXPORT  DMA0_Channel4_IRQHandler          [WEAK]          
                EXPORT  DMA0_Channel5_IRQHandler          [WEAK]          
                EXPORT  DMA0_Channel6_IRQHandler          [WEAK]          
                EXPORT  ADC0_1_IRQHandler                 [WEAK]         
                EXPORT  CAN0_TX_IRQHandler                [WEAK]          
                EXPORT  CAN0_RX0_IRQHandler               [WEAK]          
                EXPORT  CAN0_RX1_IRQHandler               [WEAK]           
                EXPORT  CAN0_EWMC_IRQHandler              [WEAK]           
                EXPORT  EXTI5_9_IRQHandler                [WEAK]           
                EXPORT  TIMER0_BRK_TIMER8_IRQHandler      [WEAK]  
                EXPORT  TIMER0_UP_TIMER9_IRQHandler       [WEAK]  
                EXPORT  TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
                EXPORT  TIMER0_Channel_IRQHandler         [WEAK]        
                EXPORT  TIMER1_IRQHandler                 [WEAK]       
                EXPORT  TIMER2_IRQHandler                 [WEAK]           
                EXPORT  TIMER3_IRQHandler                 [WEAK]           
                EXPORT  I2C0_EV_IRQHandler                [WEAK]          
                EXPORT  I2C0_ER_IRQHandler                [WEAK]         
                EXPORT  I2C1_EV_IRQHandler                [WEAK]         
                EXPORT  I2C1_ER_IRQHandler                [WEAK]         
                EXPORT  SPI0_IRQHandler                   [WEAK]        
                EXPORT  SPI1_IRQHandler                   [WEAK]          
                EXPORT  USART0_IRQHandler                 [WEAK]         
                EXPORT  USART1_IRQHandler                 [WEAK]         
                EXPORT  USART2_IRQHandler                 [WEAK]        
                EXPORT  EXTI10_15_IRQHandler              [WEAK]        
                EXPORT  RTC_Alarm_IRQHandler              [WEAK]        
                EXPORT  USBFS_WKUP_IRQHandler             [WEAK]        
                EXPORT  TIMER7_BRK_TIMER11_IRQHandler     [WEAK] 
                EXPORT  TIMER7_UP_TIMER12_IRQHandler      [WEAK] 
                EXPORT  TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
                EXPORT  TIMER7_Channel_IRQHandler         [WEAK] 
                EXPORT  EXMC_IRQHandler                   [WEAK]         
                EXPORT  TIMER4_IRQHandler                 [WEAK]           
                EXPORT  SPI2_IRQHandler                   [WEAK]          
                EXPORT  UART3_IRQHandler                  [WEAK]          
                EXPORT  UART4_IRQHandler                  [WEAK]          
                EXPORT  TIMER5_IRQHandler                 [WEAK]         
                EXPORT  TIMER6_IRQHandler                 [WEAK]        
                EXPORT  DMA1_Channel0_IRQHandler          [WEAK]          
                EXPORT  DMA1_Channel1_IRQHandler          [WEAK]          
                EXPORT  DMA1_Channel2_IRQHandler          [WEAK]         
                EXPORT  DMA1_Channel3_IRQHandler          [WEAK]         
                EXPORT  DMA1_Channel4_IRQHandler          [WEAK]          
                EXPORT  CAN1_TX_IRQHandler                [WEAK]          
                EXPORT  CAN1_RX0_IRQHandler               [WEAK]         
                EXPORT  CAN1_RX1_IRQHandler               [WEAK]          
                EXPORT  CAN1_EWMC_IRQHandler              [WEAK]          
                EXPORT  USBFS_IRQHandler                  [WEAK]          
  
;/* external interrupts handler */
WWDGT_IRQHandler                  
LVD_IRQHandler                    
TAMPER_IRQHandler           
RTC_IRQHandler               
FMC_IRQHandler                   
RCU_CTC_IRQHandler                   
EXTI0_IRQHandler                  
EXTI1_IRQHandler                 
EXTI2_IRQHandler                
EXTI3_IRQHandler                 
EXTI4_IRQHandler                  
DMA0_Channel0_IRQHandler         
DMA0_Channel1_IRQHandler          
DMA0_Channel2_IRQHandler        
DMA0_Channel3_IRQHandler         
DMA0_Channel4_IRQHandler          
DMA0_Channel5_IRQHandler          
DMA0_Channel6_IRQHandler          
ADC0_1_IRQHandler                   
CAN0_TX_IRQHandler                
CAN0_RX0_IRQHandler               
CAN0_RX1_IRQHandler               
CAN0_EWMC_IRQHandler               
EXTI5_9_IRQHandler                
TIMER0_BRK_TIMER8_IRQHandler    
TIMER0_UP_TIMER9_IRQHandler   
TIMER0_TRG_CMT_TIMER10_IRQHandler 
TIMER0_Channel_IRQHandler        
TIMER1_IRQHandler             
TIMER2_IRQHandler                 
TIMER3_IRQHandler                 
I2C0_EV_IRQHandler                
I2C0_ER_IRQHandler               
I2C1_EV_IRQHandler               
I2C1_ER_IRQHandler               
SPI0_IRQHandler                  
SPI1_IRQHandler                   
USART0_IRQHandler                 
USART1_IRQHandler                 
USART2_IRQHandler                
EXTI10_15_IRQHandler              
RTC_Alarm_IRQHandler             
USBFS_WKUP_IRQHandler             
TIMER7_BRK_TIMER11_IRQHandler   
TIMER7_UP_TIMER12_IRQHandler  
TIMER7_TRG_CMT_TIMER13_IRQHandler 
TIMER7_Channel_IRQHandler         
EXMC_IRQHandler                   
TIMER4_IRQHandler                 
SPI2_IRQHandler                  
UART3_IRQHandler                  
UART4_IRQHandler                  
TIMER5_IRQHandler             

TIMER6_IRQHandler                
DMA1_Channel0_IRQHandler          
DMA1_Channel1_IRQHandler         
DMA1_Channel2_IRQHandler         
DMA1_Channel3_IRQHandler         
DMA1_Channel4_IRQHandler          
CAN1_TX_IRQHandler                
CAN1_RX0_IRQHandler              
CAN1_RX1_IRQHandler               
CAN1_EWMC_IRQHandler               
USBFS_IRQHandler                  
;B  .跳转到当前位置,网上有人说是跳到这里无限循环,我自己理解是跳到这里补再返回了,不存在什么无限循环,只是不能往下跳转了而已
                B       .
                ENDP
;这里ALIGN表示自己对齐,ALIGN 后面什么都没有?默认是4字节对齐?8字节对齐?网上有网友给出答案
;ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐
                ALIGN

; user Initial Stack & Heap
;IF ELSE ENDIF汇编的这些指令已经和C语言差不多了,^_^
;如何才能确定有没有定义__MICORLIB,在编译器中有选项Use MicroLIB,如果有勾选则__MICROLIB会被定义,外面
;就可以用__initial_sp,__heap_base,__heap_limit这些在本文件中声明的label
                IF      :DEF:__MICROLIB

                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE
;__use_two_region_memory 指定栈和堆是分两个区域,双区模式,也有单区模式的
                IMPORT  __use_two_region_memory
;EXPORT表示可以导入到外面,被其他文件所调用,类似于C语言中的extern      
                EXPORT  __user_initial_stackheap
;看下这个PROC子程序
__user_initial_stackheap PROC
;将Heap_Mem地址也就是堆的基地址放入到R0寄存器中,R0~R15的寄存器要看下功能
                LDR     R0, =  Heap_Mem
;R1中放的是栈的最高地址            
                LDR     R1, =(Stack_Mem + Stack_Size)
;R2中放的是堆的最高地址                
                LDR     R2, = (Heap_Mem +  Heap_Size)
;R3中放的是栈区的基地址                
                LDR     R3, = Stack_Mem
;BX LR的作用等同于mov PC,LR,即跳转到LR中存放的地址处。
;LR是链接寄存器(Link Register LR),在ARM体系结构体中LR的特殊用途有两种:一种是用来保存子程序的返回地址,这里在外面调用这个子程序的时候
;子程序的返回地址已经自动保存到LR(R14)寄存器中了;二是当异常发生时候,LR中保存的值等于异常发生时PC的值减去4(或者减去2),因此在各种模式下可以
;根据LR的值返回到异常发生前的响应位置继续执行。
;当前通过BL或者BLX指令(注意这里是带L(链接)的)调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时候,把LR的值复制到程序
计数器PC即可实现子程序返回。                
                BX      LR
;ENDP 子程序结束                
                ENDP
;模式4字节对齐,如果是ALIGN 3,则是2^3字节对齐
                ALIGN
;ENDIF 和前面IF ELSE 对应                
                ENDIF
;END 表示汇编程序结束,后面再有也不会汇编了
                END

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值