5

设置rax为 1 的最短 Intel x86-64 操作码是多少?

我试过xor rax,raxand inc al(在 NASM 语法中);它给出了 5 字节的操作码48 31 c0 fe c0。是否有可能在 4 个字节中实现相同的结果?

您可以修改或读取任何其他寄存器,但不能假定先前指令中的任何一个都具有特定值。

4

2 回答 2

6

由于 push 有一个字节立即编码,而寄存器有一个字节 pop,这可以在三个字节中完成:6a 01 58push $1 / pop %rax.

于 2015-11-20T14:42:15.513 回答
2

在任何已知的前提条件下,有一些技巧比 push imm8/pop rax 3 字节解决方案更有效(在速度方面)。

因为速度mov eax, 1有很多优势,因为它没有任何输入依赖,而且只有一条指令。乱序执行可以在它(以及任何依赖它的东西)上开始,而无需等待其他东西。(参见Agner Fog 的指南标签 wiki)。

显然,其中许多利用了编写 32 位寄存器将上半部分归零的事实,以避免 OP 代码的不必要的 REX 前缀。(另请注意,在 Silvermont 上,这xor rax,rax不是特殊情况下的归零习惯用法。它仅识别 32 位寄存器的异或归零,例如 eax 或 r10d,而不是 rax 或 r10。)


如果您在任何寄存器中有一个小的已知常数开始,您可以使用

lea   eax, [rcx+1]    ; 3 bytes: opcode + ModRM + disp8

disp8 可以编码从 -128 到 +127 的位移。


如果eax中有奇数,and eax, 1也是3个字节。


在 32 位代码中,inc eax只占用一个字节,但这些 inc/dec 操作码被重新用作 AMD64 的 REX 前缀。所以xor eax,eax/inc eax在 x86-64 代码中是 4 个字节,但在 32 位代码中只有 3 个字节。尽管如此,如果在 a 上保存 1 个字节mov eax,1就足够了,并且 LEA 或 AND 不起作用,那么这比 push/pop 更有效。

于 2016-09-14T17:50:56.167 回答