类汇编语言编译器上的PC相对寻址

时间:2016-08-26 19:23:22

标签: assembly compiler-construction relative-addressing

我目前正在为自定义类似asm的编程语言编写编译器 我真的很困惑如何对数据标签进行适当的PC相对寻址。

main    LDA RA hello
        IPT #32
        HLT

hello   .STR "Hello, world!"

编译后,上面的伪代码会产生以下十六进制:

31 80 F0 20 F0 0C 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00

3180F020F00CLDAIPTHLT说明。

如代码所示,LDA指令使用标签hello作为参数。在编译时,它变为值02,这意味着"增加PC + 0x02" (如果您查看代码,那就是" Hello,world!"行相对于LDA调用的位置。 问题是:.STR不是指令,因为它只告诉编译器它需要在可执行文件的末尾添加一个(0终止的)字符串,所以,在{{1}之后是否有其他指令} label声明,该偏移量是错误的。

但我无法找到计算正确偏移量的方法,除了让编译器能够穿越时间。我是否必须"编译"它两次?首先是数据标签,然后是实际指示?

1 个答案:

答案 0 :(得分:2)

是的,大多数装配工(至少)是两次通过 - 正是因为像这样的前向参考。添加宏功能可以添加更多传递。

查看汇编列表,而不仅仅是操作码。正如你所说的实际偏移是“2”,我假设存储器是字寻址的。

<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>

前两列是PC和操作码。我不确定0000 3180 main LDA RA hello 0001 F020 IPT #32 0002 F00C HLT 0003 4865 hello .STR "Hello, world!" 指令是如何编码的(那里的LDA偏移位置在哪里?)

在第一遍中,假设所有寻址都是相对的,则assmebler将发出操作码的固定部分(覆盖+2部分)以及标记,以显示需要修补指令第二遍中LDA RA的地址。

此时它知道最终机器语言的大小,但不知道它的完整值。

然后继续,计算每条指令的地址并构建其符号表。

在第二遍中,现在知道上述信息,它通过计算相对偏移等来修补每条指令。它还经常重新生成整个输出(包括PC值)。

偶尔会在第二遍中检测到某些东西,这会阻止它继续。例如,您可能只能引用256个单词(-127到+128)内的对象,但标签hello结果超过128个单词。这意味着它应该使用双字指令(带有绝对地址),这会改变它在第一次传递过程中学到的所有内容。

这通常被称为“修复”错误。在链接阶段也会发生同样的事情。

只有坚持'使用前定义'才能实现单通道汇编程序。在这种情况下,您的代码会将hello报告为未定义的符号。

您还需要阅读“计划部分”。虽然hello不是可执行指令,但 是汇编程序的指令,用于将字符串的二进制表示放入图像的CODE部分(vs DATA)。