https://sourceware.org/binutils/docs-2.28/as/Symbols.html
符号是一个中心概念,程序员使用符号命名事物,链接器使用符号链接、调试器使用符号调试。
警告:as在目标文件放置符号时,不会按照符号声明的顺序,这可能摧毁一些调试器。
标签是立即跟着一个冒号:的符号。符号表示了active location counter的当前值,而且可作为指令操作数。当你使用同样的符号表示两个地址,你会被警告。第一个定义覆盖其它定义。
符号可以被赋与任何值,通过符号接一个=,再接任何表达式。这等价于.set指令。同样的双等==,等价于.eqv指令。
符号名以字母或.-开头。大多数机器上,$也可用于符号名。后续的字母可以使用字母、数字、美元符号(某些机器不允许)和下划线。
字母的大小写是有意义的。
符号名不能以数字开始,例外是本地标签。
多字节字符是支持的,包含多字节字符的符号名需要使用双引号,且需要转义码。标签不支持多字节字符。
一个符号只有一个名字,每个名字严格指向一个符号。可以多次使用符号名。
Local symbol names
本地符号是以特定的local label prefixes开头的符号,对ELF系统来说,默认的本地标签前缀是.L。传统的a.out系统是L。但每个目标有它自己的本地标签前缀集。
本地符号在汇编器内部定义和使用,通常不存储到目标文件。因此,在调试时它们是不可见的。可以使用-L选项保留本地符号到目标文件。
Local Labels
本地标签和本地符号不同,本地标签帮助编译器和程序员临时使用名字。它们(本地标签)创建输入源码作用域内唯一的符号,可以通过简单的符号使用。为了定义一个本地标签,以N:的格式写一个标签,N为任何非负整数。使用Nb引用最近定义的本地标签,使用Nf引用下一个定义的本地标签,b代表backwards,f代表forwards。
没有限制如何使用这些标签, 你可以重复使用。需要一个例子:
1 2 3 4 | 1: branch 1f 2: branch 1b 1: branch 2f 2: branch 1b |
第一行跳到下一个1,即第三行;第二行跳到上一个1,即第一行。
本地标签名仅仅用于计数。在汇编器使用它们之前,会立即被转换成一个更方便的符号名,符号名存储到符号表,可出现在错误消息中,可以发射到目标文件。名字由3个部分组成。
local label prefix
和系统相关,通常as和ld会忘记这些以本地标签前缀开始的符号。这些标签用于那些你绝对不会用的符号。如果使用-L选项,as保留这些符号到目标文件。也可以指示ld保留这些符号,便于在调试中使用它们。
number
就是本地标签定义使用的数字。如果用55:写本地标签,那数字就是55。
C-B
这个不常用的符号用来避免冲突,其ASCII值为\002 (control-B)。
例如,第一个本地标签:1,可能被命名为.L3C-B1。
Dollar local labels
在一些目标上,as支持更多的本地标签形式,叫做dollar labels,他们的作用域更小。而普通的本地标签,作用域是整个文件。
美元本地标签以数字开始、美元结束。如:55$:
和普通标签不同,它们的转换名字使用\001字符,如第5个6$定义可命名为.L6C-A5
特殊符号.指向当前地址。
因此,表达式`melvin: .long .'。定义melvin包含它自己的地址。把值赋给.被当做.org指令处理。因此,表达式`.=.+4'和`.space 4'相同。
每个符号有名字、属性 “value”和 “type”。根据输出格式,符号也可以有其它辅助属性。
如果你使用符号,而没有定义它,as假设它所有的属性都为0,而且可能不会警告你。这使符号变成一个外部定义符号,这通常是你所期望的。
Value
符号值通常是32位。对于一个标签text, data, bss或者absolute section地址的符号,其值是标签相对于section开始处的偏移地址值。自然而然,对于text, data和bss section,当ld在链接阶段改变section的基地址时,符号的值会改变。绝对符号的值在链接时不变,这也是他们称之为绝对的原因。
未定义符号的值,以一种特殊的方式对待。如果是0,则符号在当前汇编代码中未定义,ld试图从别的文件决定它的值。你使用这种符号仅仅提到符号的名字,但是不定义它。一个非0的值,表达了一个.comm公用声明。公用存储的值是多少是被保留的,以字节(地址)。符号指向分配的存储的第一个地址。
Type
类型属性包含了符号的重定向信息。一些标志设置表示符号是外部的、可选的、以及链接和调试的其它信息。