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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章