在未来符号的情况下,汇编程序不知道类型 缺失符号的(绝对的或可重定位的)。因此它不能 生成重定位位...
未来符号是在声明之前遇到的符号。例如:
$conn = new PDO(.....);
$stm = $conn->prepare("INSERT INTO table (str_value) :value");
$stm->execute(array(':value' => $string));
组装 JMP TO
...
TO: ADD 1,2
指令时,符号JMP TO
是未来符号,因为尚未遇到其定义。
由于符号指的是内存中的某个位置,它怎么能不可重定位?
答案 0 :(得分:0)
我没去看你的书。我喜欢它谈论汇编程序和链接器的历史,它当时正在做的,但是工具现在好多了。
你非常对。我认为有一些指令集,不需要特定于一个指令集,提供近乎版本的事物或指令,通过引用基本上应用于程序计数器的一些偏移量是引用或跳转到的地方。并且在某种程度上还提供了一种方法来使用在(可变长度)指令中编码的绝对地址,或者可以跳转到从位置(pc相对)或通过立即mov等加载的寄存器中的地址。我认为这位作者所暗示的是,一旦你对该地址进行硬编码,它就永远被修复,绝对并且链接器永远不会再改变它。
好吧,我只需要花几秒钟来证明一下连接器今天能做什么。它们可以并且将修改指令和/或生成所需的指令,而不是汇编程序执行所有指令生成。即使你有汇编程序完成整个事情你仍然没有卡住,汇编程序也不会完成所有事情,汇编程序会例如对附近的某个位置执行pc相对读取,该位置对汇编程序和链接程序是已知的是一个不在这个对象中的标签的地址,一个外部的。汇编器将所有近端负载的CODE写入寄存器跳转寄存器,链接器填写地址。一旦链接看起来像一个绝对地址,但链接器可能已经重新定位,并且可以认为使用的二进制格式可以指示该位置是某个标签的地址,因此即使在加载时加载器也可以更改它。
有些指令集可以将绝对地址放在指令中,并且链接器无法负责在链接时填写指令的那一部分。
我认为唯一的问题情况只是糟糕的设计,如果在一个对象中你已经解决了一个标签并使用了pc相对跳跃,但不知何故,工具链允许你分开该对象的一部分并将其与休息。那只是糟糕的设计。一个情况,gnu工具至少处理得很好,没有理由为什么其他人无法取得手臂和拇指bl指令不能改变模式,所以如果没有告知否则汇编程序假定某个标签的bl将处于相同的模式因为你的程序员使用bl而不是blx或bx。链接器出现并发现标签处于另一种模式,如果它可以在触及范围内找到空间,则会在相同模式下添加蹦床几条指令,这些指令在功能上是不可见的(返回地址被保留,模式被更改并且到达目的地标签/地址)。非常酷,我在SO上发布了这个例子。
当链接器找不到它被绘制到角落的空间,它不能制作蹦床,它需要插入到对象中的指令不适合并且它们不能在该指令集的规则内进行蹦床时,问题就出现了,然后链接器必须纾困。我认为今天纾困的门槛与当时的门槛大不相同。即使在上面的情况下,gnu连接器和其他人在几个版本之前也不那么聪明,少数几年或更少,他们会挽救这种情况而不是仅仅修复它。我认为在手臂的情况下,如果你保持相同的模式,并试图在地址空间太远,它将纾困而不是只是修复它。它也可以很容易地解决这个问题。