汇编器和符号表的用途是什么?什么是交易品种的地址?



来自我的教科书:

为了在汇编语言程序中生成每个指令的二进制版本,汇编程序必须确定对应于所有标签的地址。汇编程序跟踪分支中使用的标签和符号表中的数据传输指令。如您所料,该表包含符号和地址对。

为什么需要符号表?如果我们有一个带有标签名称和地址的符号表,地址有什么用?地址是什么...只是标签的名称?还是标签的说明?

假设我们在汇编 MIPS 中有这样的指令:

add_numbers:
addi, $s0, $t0, 2

为什么符号表不只存储add_numbers | <the_binary_representation_of_the_instruction>而不是add_numbers | <address_location_of_label>

标签是一个地址,它是程序员向汇编程序提供地址的一种方式,但不必知道物理地址。 让工具链为您完成这项工作。

我不记得我的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。 一行。如果你添加几十行,几百行。 您将如何跟踪这一切? 通过在评论中贴标签? 一遍又一遍地组装、拆卸和修补源代码,直到它看起来有点正确,并希望没有错误。

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。

最新更新