ARM汇编--汇编中符号和变量

     习惯了使用C语言的情况下我发现自己对与汇编程序的符号和变量的理解很不深刻,今天抽空来学学加深理解。以ARM汇编来说,在汇编代码中所有以"."开头的指令都是汇编伪指令他们不属于ARM指令集。常常在汇编代码中看到如下的使用方式但很少深入理解这样的写法的深层实现意义。究竟这两种使用方式区别是什么呢?

.global    xxxx
.word     xxxx

查阅GNU的汇编伪指令说明后按我理解的我将两者按如下的方式解释:

.global

修饰标号为全局的,用法 .global xxx 这个符号可以被当前源文件以外的其他文件使用也可以被连接脚本(连接器)使用,xxx仅仅是一个标号对应一个地址并不是C中的一个变量。
无法对他取地址,因为他本身代表一个地址,仅仅是一个对应到一个编译过程中的值的别名,类似C代码中的define 定义的一样,只是在链接时他的值是由连接器自动处理的。
汇编代码使用仅能使用ldr,Rx,=xxx;而不能使用ldr,Rx,xxx

.word

汇编一个字的内存块,用法 .word expressions 这个expressions 可以是一个数也可以是一个符号或表达式。 如果是一个数则这里直接放置的就是这个值。如果是一个标号则
这个标号最后值就会存放这里,标号的值就是这块内存的地址。可以在C语言中直接使用extern uint32_t expressions来读写这个变量。
汇编中的使用同.global。expressions还可以是连接脚本中定义的符号。

这里 和word相同的功能的伪指令还有

.byte 			;定义单字节数据                
.hword/.short  ;定义双字节数据              
.word/.long /.int ;定义4字节数据                  
.quad  			;定义8字节数据                 
.float/.single ;定义32bit 浮点数             
.double  ;定义64bit浮点数             
.ascii ;定义字符串以/0为结束符       
例: .ascii    "hello"
.asciz /.string  ;定义字符串(非零结束符)  
例: .string   "hello"
.fill     				;分配一段字节内存单元,用size长度value填充repeat次  
例:  .fill   10,2,6   	;将两个字节长度的6重复填充10次
.zero                   ;分配一段字节内存单元,并用0填充内存                          
例:  .zero  10   		;分配十个字节单元,并用0填充
.space/.skip        	;分配一段内存单元,用value将内存单元初始化               
例:  .space  10,6  	;分配十个字节单元,并用6填充

实例代码(来自liteos):

    /* 修饰标号 __LOS_HEAP_ADDR_START__  下同 */
    .global __LOS_HEAP_ADDR_START__
    .global __LOS_HEAP_ADDR_END__
    /* 定义标号 __LOS_HEAP_ADDR_START__  下同 */    
__LOS_HEAP_ADDR_START__:
    .word  __los_heap_addr_start__
__LOS_HEAP_ADDR_END__:
    .word  __los_heap_addr_end__

符号(或标号)

仅存在程序构建过程而不存在于最终目标文件中,常常配合编译和链接脚本使用,其保存的是地址信息

变量

最终会在运行RAM中找到,如果是全局的就会一直存在。符号或标号指向一个地址,如下就是定义变量(连接器会预留这块内存),__los_heap_addr_start__指向一块内存,他的意思更像C语言中的变量实际对应特定地址的内存。

顺带查到的伪指令记一下:

.syntax

ARM架构下使用的定义汇编语法格式伪指令,用法 .syntax [unified | divided],其中divided为缺省值。 divided 此时使用旧的汇编风格,此时ARM和THUMB指令有着各自的语法。 使用unified时,ARM和THUMB指令使用统一的语法,有着以下的主要特性:

立即数不需要#前缀 可能会出现IT指令,如果出现,则根据后面的条件码进行验证。

在ARM模式下,它不会生成机器码,而在THUMB模式下则会生成机器码

对于ARM指令,条件码总是出现在指令的最后;对于THUMB指令,条件码可以被使用,但仅限于IT指令的范围内 V6T2架构(及更高版本)的所有新指令都可用(这些指令中,divided语法仅支持少部分) 支持.N和.W后缀

.thumb 指定使用thumb指令集

.cpu 指定cpu类型如cortex-m0

.fpu 指点浮点计算指令的类型,有soft,softfp,hard 具体参考编译器的帮助文档一般在编译器路径的/share下有编译器的帮助文档。

.arch 指定代码目标架构,如armv7-a

.type 指定符号类型

参考源码地址:https://gitee.com/LiteOS/LiteOS/blob/master/targets/Cloud_STM32F429IGTx_FIRE/los_startup_gcc.S

参考博客:https://blog.csdn.net/gameit/article/details/13169307

原文地址:https://www.cnblogs.com/w-smile/p/14064425.html