汇编语言 - 即使在允许未对齐数据的架构中,指令是否也必须对齐?

4
我知道一些像Intel x86这样的小端架构允许不对齐的数据访问。当然,直觉上讲,不对齐并不是很聪明,因为它可能会降低性能(对于现代芯片来说并不一定如此处所辩护)。因此,未对齐的数据访问可能并不好,但在某些架构中是合法的。

直到最近,我认为未对齐的指令也适用相同的规则:如果给定处理器可以处理数据的不对齐,那么什么可以阻止它对代码执行相同的操作呢?然而,在 Linda Null 的书中(这里),明确说明了相反的情况:

通常,现实中的妥协是使用两到三个指令长度,这提供了易于区分和简单解码的位模式。指令长度还必须与机器上的字长进行比较。如果指令长度恰好等于字长,则存储在主存储器中时指令完全对齐。出于寻址原因,指令始终需要按照字对齐。 因此,大小为实际字长一半、四分之一、双倍或三倍的指令可能会浪费空间。可变长度指令显然不是相同大小,需要按字对齐,从而导致空间损失。
另一方面,许多Google图书中自然地谈论了未对齐的指令。因此,我的问题是:
1. 某些体系结构是否允许未对齐的指令? 2. 任何大端架构是否要求对齐?我理解只有小端处理器可能出现不对齐。
我对此正确吗?
我希望您能帮助我澄清这些问题。非常感谢!

1
这个问题很难回答,因为在指令对齐不确定的平台上,也可以看作是指令对齐要求为1的平台。指令对齐可以比指令长度小;例如,在ARM Thumb上,32位长的指令(如bl)只需要对齐到16位即可。 - fuz
1
处理器可以像处理数据一样处理不对齐的指令。一些精简指令集(RISC)只是省略控制转移指令操作数中的低位,因为它们的空间有限。此外,取指单元可以与(更复杂的)加载单元不同。由于代码是针对特定架构创建的(而数据是通用的),对其施加约束是合理的,也不会给任何人带来太大负担。 - Margaret Bloom
4
像x86这样具有可变指令长度的架构通常(总是?)允许不对齐的指令,否则将会有效地取消可变长度的优势。话虽如此,它们仍然希望诸如分支目标(特别是循环)之类的内容保持对齐。 - Jester
给Jester和@MargaretBloom - 这对我来说很有意义:允许可变长度指令,然后因为对齐原因而放弃它们是没有意义的。听起来很自然。然而,我在论坛上看到有人说可变长度指令必须通过使用NOP指令进行“规范化”(即对齐),这让我想知道:x86是否实际支持不对齐的指令,或者我们(实际上是编译器)必须用NOP填充内存,从而浪费空间? - Humberto Fioravante Ferro
1个回答

2
没有通用的答案,您必须分别查看每个设计。此外,该设计对字节序的要求也需要考虑。我不明白您如何试图将字节序和对齐方式联系起来。有些架构非常流行,如果单独考虑每个架构,要么没有选择,要么有一个流行的字节序选择,而该架构内部与字节序无关的是其对齐规则。
x86按定义是一个8位指令集,始于很久以前的一个8位或16位总线,具体取决于您购买或连接的方式,因此按定义没有对齐方式。由于其指令长度可变且由多个字节组成,因此它不能有对齐规则。由于其历史原因,它也没有数据对齐规则,这进一步损害了其性能。
以MIPS为例,不幸的是,我不知道传统的字节序是大端还是小端,但人们称其为双端,这应该引起警惕。但是,在这里,字节序和对齐没有理由结合在一起。 MIPS作为教育概念存在,并保留着物理上建立或至少可以为自己的设计购买核心,其目的是提高性能,尽管这会让程序员感到痛苦,但强制对齐与此非常契合。自然而然地,指令获取和数据读取应该遵循相同的规则,指令集是32位指令,最好也是对齐的。
从早期开始,ARM强制对齐,但即使在ARM7TDMI上,您也可以禁用它,并且尽管ARM ARM所说的行为是可预测的,但实际上很奇怪(在单词内旋转而不是溢出到另一个单词中)。由于x86懒惰的程序员,他们更容忍允许不对齐的传输,通过禁用故障陷阱得到结果,结果会像我们所期望的那样,溢出到下一个单词中。这里列为双端机器,但明智的解决方案是转到小端,工具和一切都有意义,它们的字节序从BE-32变为BE-8在armv6中进一步引起大端痛苦,只需远离即可。例外是StrongARM,它成为XScale,我认为Marvel买了它(或者是Cavium?),默认为大端(BE-32),并且很难使用工具,但尽管能够运行小端,但这些社区仍然运行大端。我想记住,ARM设计要求指令获取对齐,而数据如果禁用故障则不必对齐。指令始终是小端的,独立于大/小设置。它们还具有16位指令集拇指和拇指2扩展,这些是可变长度的拇指,它们不需要对齐,它们是16位指令的可变长度,而不是将其视为32位指令。解码器必须检查第一个16位指令以了解接下来的指令是否连接。就像x86一样。
RISC倾向于在性能上胜过CISC,因此RISC设计往往具有对齐规则,但没人不能制作完全不对齐的RISC或完全对齐的CISC。不要让自己陷入概括任何一种设计的陷阱,必须单独查看每个架构和/或核心,即使在供应商或指令集(xscale vs ARM7TMDI)内也是如此。
对齐始终影响性能,今天、昨天和明天都是如此。有时影响较小,有时影响较大,但你无法在设计中随意增加硅片或电线,因此你不能改变总线的工作方式以及一个时钟周期内可以装入多少内容。因此,除非它严格限于字节宽度或位宽度总线,否则没有新技术可以消除对齐性能影响。回到8位总线不会更快,die里更宽的总线才更快。芯片外部的窄总线并不更快,但更易处理,因此SATA优于PATA。这只是因为我们无法将许多高速信号并行处理,需要串行化它们(可以有许多单独的串行接口一起工作,如PCI、以太网)。因此,对于CPU核心架构,对齐始终很重要,因为我们使用二进制状态和每个总线固定数量的位。

老司机,你的回答看起来很有把握,让我不得不重新阅读朱莉娅·纳尔在她的书中所写的内容:“大多数使用大端方案的架构不允许在非字地址边界上写入字...这浪费空间。小端架构(如英特尔)允许奇地址读取和写入,这使得在这些机器上编程更加容易。”因此,她确实没有说大端架构需要内存对齐。但是,你是否同意她说过所有小端架构都支持非对齐访问? - Humberto Fioravante Ferro
1
在编程中,必须小心使用像“全部”这样的词,因为只需要一个人找到或创建一个例外,那么这个说法就不再正确了。关键是这并不重要。仔细审查你正在使用或感兴趣的体系结构,如果最终选择使用它,你迟早会做到的...就像人们试图在哈佛架构和冯·诺伊曼架构之间使用的概括一样。 - old_timer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接