在armasm_user_guide中有这样一段话:
Labels
A label is a symbol that represents the memory address of an instruction or data.
The address can be PC-relative, register-relative, or absolute. Labels are local to the source file unlessyou make them global using the EXPORT directive.
The address given by a label is calculated during assembly. armasm calculates the address of a label relative to the origin of the section where the label is defined. A reference to a label within the same section can use the PC plus or minus an offset. This is called PC-relative addressing.
Addresses of labels in other sections are calculated at link time, when the linker has allocated specific locations in memory for each section.
可以理解为:
1 asm代码中的Labels,只是表示一个地址,在C代码中引用时,要用取地址指令&取得地址使用。
2 如果标号对应的地址,有用了DCD等指令分配空间并指定了初始值,则在C代码中引用时,对应标号的地址和值都是有意义的。
在startup_gd32w51x.s中有如下代码:
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__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_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
; /* reset Vector Mapped to at Address 0 */
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
我们可以分析一下__Vectors和__initial_sp这两个标号的含义,然后写一段C代码测试验证一下
1 __initial_sp是一个标号,表示一个地址,这个地址是栈顶位置。
2 __Vectors也是一个标号,表示一个地址,这个地址是中断向量表的起始地址,这个地址存的第一个32位数据是栈顶位置。
C语言测试代码如下:
/*
向量表的地址,就是它在ROM中的位置,一般是在FLASH开始的地方。
向量表的值(调试的时候看到的值),是对应地址的第一个INT值。
就是__initial_sp的地址,而__initial_sp指向的值,是没有初始化的。
*/
if (1) {
extern uint32_t __Vectors;
extern uint32_t __initial_sp;
volatile uint32_t v1_val = __Vectors; //栈顶位置
volatile uint32_t v1_addr = (uint32_t) &__Vectors; //向量表地址
volatile uint32_t v2_val = __initial_sp; //未初始化的值
volatile uint32_t v2_addr = (uint32_t) &__initial_sp; //栈顶位置
(void)v1_val;
(void)v1_addr;
(void)v2_val;
(void)v2_addr;
}