标签是地址,它是程序员向汇编程序提供地址但不必知道物理地址的一种方式。让工具链为您完成这项工作。
我不记得我的 MIPS 手头了,所以这里有一些伪代码。
loop_top:
nop
nop
sub r0,1
cmp r0,0
bne loop_top
取决于指令集,但通常条件分支将是 pc 相关的。通常在组装过程中使用的表格在表格上进行一次或多次传递将解析分支与目的地之间的距离,以便可以对分支进行完整编码。上述大多数指令集都可以一次性解决。 loop_top 是一个带有地址的标签,但是对于这里的分支来说,它是 pc 相关的,你不需要知道物理地址。
但是
call my_fun
一旦通过代码,汇编器发现 my_fun 没有在这个文件中定义和/或汇编语言有一些语法在使用之前将它标记为外部。无论哪种方式,它都是外部的。组装此文件时无法解析。因此需要表来指示标签名称,以及该指令在该对象中的位置,取决于汇编器,它可能暂时将临时偏移量或完整地址填充为零,或者将其编码为无限循环。
链接器稍后确定处理器内存空间中事物的实际地址,链接器最终将拥有一个表,其中包含所有(工具链此阶段的相关标签)标签及其在链接时的地址,然后链接器将返回进入代码并修复/创建此调用指令的机器代码,因为它知道该标签的实际地址是什么。
j hello
对象:
Disassembly of section .text:
00000000 <.text>:
0: 08000000 j 0x0
4: 00000000 nop
另一个对象:
.globl hello
hello:
j hello
.word hello
链接他们
Disassembly of section .text:
00001000 <_ftext>:
1000: 08000402 j 1008 <hello>
1004: 00000000 nop
00001008 <hello>:
1008: 08000402 j 1008 <hello>
100c: 00000000 nop
1010: 00001008 0x1008
作为对象,所有工具链必须继续使用标签 hello 作为稍后解析的地址。在这种情况下,在链接时,链接器通过对象工作,计算字节数,形成标签及其地址的表。在第一次或其他一些过程中,它将根据需要更改指令或数据以解析这些标签。
现在老式的汇编器从同一个源文件进行汇编和链接工作,声明“汇编器必须确定与所有标签对应的地址”。执行链接器工作的通常不是具有常用工具链的汇编器。因此,引用的声明可以使用一些改进。但希望这表明标签是地址,它们代表一个尚未确定的地址,因此代码比这样的代码更容易编写
nop
nop
j pc-2
那么如果你添加另一个指令
nop
add r0,r1
nop
j pc-3
或者
j 0x1008
然后必须花费大量时间重写程序以将每个地址硬编码到程序中。添加/删除一行,并且必须更改许多其他代码。代表地址的标签使这一切变得更加容易,工具链确定地址,然后返回并用地址替换标签......
添加了一个 nop:
Disassembly of section .text:
00001000 <_ftext>:
1000: 08000403 j 100c <hello>
1004: 00000000 nop
1008: 00000000 nop
0000100c <hello>:
100c: 08000403 j 100c <hello>
1010: 00000000 nop
1014: 0000100c
如果我们没有标签并且不得不硬编码地址,那么您将不得不更改这三个位置作为 nop 的结果。一条线。如果你添加了几十行,数百行。你将如何跟踪这一切?通过在 cmets 中放置标签?一遍又一遍地组装、拆卸和修补源代码,直到它看起来有点正确,并希望没有错误。
mips-elf-readelf -s so.elf
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00001000 0 SECTION LOCAL DEFAULT 1
2: 00400000 0 SECTION LOCAL DEFAULT 2
3: 00400018 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 0000a010 0 NOTYPE LOCAL DEFAULT 2 _gp
6: 00002018 0 NOTYPE GLOBAL DEFAULT 4 _fdata
7: 0000100c 0 OBJECT GLOBAL DEFAULT 1 hello
8: 00001000 0 NOTYPE GLOBAL DEFAULT 1 _ftext
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND _start
10: 00002018 0 NOTYPE GLOBAL DEFAULT 2 __bss_start
11: 00002018 0 NOTYPE GLOBAL DEFAULT 2 _edata
12: 00002018 0 NOTYPE GLOBAL DEFAULT 2 _end
13: 00002018 0 NOTYPE GLOBAL DEFAULT 2 _fbss
这是一个有趣的:
7: 0000100c 0 OBJECT GLOBAL DEFAULT 1 hello
标签 hello 一旦组装并链接到最终二进制文件中,就等于地址 0x100C。