我正在通过Kip Irvine的"x86处理器的汇编语言,第六版"工作,我真的非常喜欢它.
我刚才读到了以下段落中的NOP助记符:
"It [NOP] is sometimes used by compilers and assemblers to align code to
even-address boundaries."
Run Code Online (Sandbox Code Playgroud)
给出的例子是:
00000000 66 8B C3 mov ax, bx
00000003 90 nop
00000004 8B D1 mov edx, ecx
Run Code Online (Sandbox Code Playgroud)
然后该书指出:
"x86 processors are designed to load code and data more quickly from even
doubleword addresses."
Run Code Online (Sandbox Code Playgroud)
我的问题是:原因是因为对于本书所指的x86处理器(32位),CPU的字大小是32位,因此它可以将NOP中的指令拉入并处理它们走 ?如果是这种情况,我假设一个字长为四字的64位处理器会用一个假设的5字节代码和一个nop来做到这一点?
最后,在我编写代码之后,我是否应该通过NOP进行正确的对齐以优化它,或者编译器(MASM,在我的情况下),为我做这个,正如文本似乎暗示的那样?
谢谢,
斯科特
我调用.p2align了这个汇编指令,它是由gccC程序源生成的.
据我所知,对齐访问比未对齐访问更快,asm程序也不会自动对齐内存位置或优化内存访问,因此您必须这样做.
我真的无法读到这一点.p2align 4,,15,尤其是最后一部分15.
正如许多文档报道的那样,跳过明显gcc产生2 ,而不是1 的事实; 我得到的是这段asm内存以这样的方式对齐内存,即每个位置占用2 ^ 4位,这意味着16位,所以我认为WORD在这种情况下a 是16位长是公平的.
现在15可能意味着什么?这是多少比特?计数是从0这样开始的,"实际"数量是16而不是15?
编辑:
我只是将相同的C源转换为32位和64位asm代码,内存总是以相同的方式与同一指令对齐.p2align 4,,15.这是为什么 ?
如果我有一个受Intel jcc erratum约束的芯片,我如何在 gcc 中启用缓解(它调整分支位置以避免有问题的对齐),以及哪些 gcc 版本支持它?
在下面的 C++ 示例中,我定义了一个计算树最左边路径高度的函数。
struct TreeNode {
int value{};
TreeNode *l = nullptr;
TreeNode *r = nullptr;
};
int getLeftHeight(TreeNode *root) {
int height = 0;
while (root != nullptr) {
root = root->l;
height++;
}
return height;
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 9.3 或 10.1(使用 -O3)编译时,我得到以下 x86。
getLeftHeight(TreeNode*):
xor eax, eax
test rdi, rdi
je .L4
.L3:
mov rdi, QWORD PTR [rdi+8]
add eax, 1
test rdi, rdi
jne .L3
ret
.L4:
ret
Run Code Online (Sandbox Code Playgroud)
但是,在使用 Clang 10 编译时,如下图所示,没有重复的ret.
getLeftHeight(TreeNode*):
xor eax, …Run Code Online (Sandbox Code Playgroud)