assembly - 为什么代码应该与x86上的偶数地址边界对齐?

标签 assembly

我正在研究Kip Irvine的“x86处理器的汇编语言,第六版” ,非常喜欢它。

我刚刚在以下段落中了解了NOP助记符:

"It [NOP] is sometimes used by compilers and assemblers to align code to 
 even-address boundaries."

给出的示例是:
00000000   66 8B C3   mov ax, bx
00000003   90         nop
00000004   8B D1      mov edx, ecx

该书随后指出:
"x86 processors are designed to load code and data more quickly from even 
 doubleword addresses."

我的问题是:是这样的原因是因为对于本书所指的x86处理器(32位),CPU的字长为32位,因此它可以将带有NOP的指令提取为一个指令并进行处理。走 ?如果是这种情况,我假设一个字大小为四字的64位处理器将使用假设的5个字节的代码加上nop?

最后,在编写代码之后,我是否应该仔细检查并与NOP正确对齐以对其进行优化,还是应该由编译器(在我的情况下为MASM)为我执行此操作,如文本所示?

谢谢,

史考特

最佳答案

在字(对于8086)或DWORD(80386及更高版本)边界上执行的代码执行速度更快,因为处理器会提取整个(D)字。因此,如果您的指令未对齐,则加载时会出现停顿。

但是,您无法对每条指令进行双字对齐。好吧,我想您可以,但是那样您将浪费空间,处理器将不得不执行NOP指令,这将失去对齐指令的任何性能优势。

在实践中,仅在指令是分支指令的目标时,在dword(或任何其他)边界上对齐代码才有帮助,并且编译器通常会对齐函数的第一条指令,但不会对齐也可以通过以下方式达到的分支目标:掉下去。例如:

MyFunction:
    cmp ax, bx
    jnz NotEqual
    ; ... some code here
NotEqual:
    ; ... more stuff here

生成此代码的编译器通常会对齐MyFunction,因为它是一个分支目标(已通过call到达),但它不会对齐NotEqual,因为这样做会插入NOP指令,该指令在掉入时必须执行。这增加了代码大小,并降低了穿透速度。

我建议如果您只是在学习汇编语言,则不要担心像这样的事情通常会给您带来微不足道的性能提升。只需编写代码以使一切正常。它们起作用后,您可以对其进行概要分析,如果在查看概要文件数据后认为有必要,可以调整功能。

汇编程序通常不会自动为您完成此操作。

关于assembly - 为什么代码应该与x86上的偶数地址边界对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4909563/

相关文章:

syntax - 汇编代码解释

simulator - 适合初学者的汇编 IDE/模拟器

c - 为什么visual studio能识别__asm{}却不能识别汇编代码?

c - Visual Studio C 编译器中是否有单独的 bitset64 内在函数?

assembly - 为什么不允许在内存之间移动?

c - C 中的汇编 - 向后打印特定单词

assembly - 从数据库1加载字节,但printf整数显示大量

c - 在c中,变量在超出范围之前是否总是从寄存器压入堆栈?

optimization - 会无条件跳转刷新 x86_64 上的管道吗?

c - 用 C 制作一个小的 mach-o 可执行文件