将小数字加载到64位x86寄存器中

GJ.*_*GJ. 3 optimization assembly x86-64

在64位x86 CPU下,我们通常将数字-1加载到寄存器中,如:

mov     rdx, -1  //  48BAFFFFFFFFFFFFFFFF
Run Code Online (Sandbox Code Playgroud)

...这个操作码需要10个字节.

另一种方式是:

xor     rdx, rdx //  4831D2        
dec     rdx      //  48FFCA  
Run Code Online (Sandbox Code Playgroud)

...这个操作码只需要6个字节.

编辑:

正如JensBjörnhager所说(我已经测试过)xor edx, edx操作码应该清除整个rdx寄存器:

xor     edx, edx //  31D2        
dec     rdx      //  48FFCA 
Run Code Online (Sandbox Code Playgroud)

...这个操作码只需要5个字节.

编辑:

Alex找到另一个解决方案

mov     rdx, -1  // 48C7C2FFFFFFFF
Run Code Online (Sandbox Code Playgroud)

...这个操作码只需要7个字节.但是如何告诉编译器使用更短的操作码(不使用DB)?

...

什么是更快,什么更经济?

har*_*old 7

它比所有提到的更短:4883CAFF OR rdx,-1
它具有对我所知道的所有架构具有错误依赖性的令人讨厌的特性,但它不应该被提及IMO.有合理的理由使用它.例如,如果直到很久之后才需要结果,并且它处于循环中,否则它将不适合四个16字节块.此外,如果速度对于特定代码片段并不是一个大问题,那么也不要浪费宝贵的缓存空间.它也可以用于对齐原因,但是填充到下一个更高的对齐几乎肯定会更快.

至于告诉编译器这个,我还没有得到线索.


Dav*_*rtz 5

第一个要好得多.第一个没有依赖关系.第二种具有最差的依赖性之一 - 指令在它开始之前需要紧接在它之前的指令的最终结果.但是,如果你有一些其他指令,你可以在xor和之间滑动dec,这将消除依赖性,然后第二个选项可能会胜出.

第二个也有错误依赖于rdx第一个没有的值.一些CPU可能足够智能以识别这种错误依赖性并且不会使第一条指令停止,直到rdx知道值为止(因为输出为零,无论如何).某些x86 CPU确实具有忽略某些错误依赖性的逻辑.

比较代码字节数并不是很有用.在大多数现实条件下,代码占用的字节数非常大.

  • [`xor edx,edx` 在每一个比 PII / PIII 更新的无序 x86 CPU 上都具有破坏性](/sf/ask/2356663221/ -set-a-register-to-zero-in-x86-assembly-xor-mov-or-and),因此它可以在发出后立即运行。在 Intel SnB 系列上,归零习惯用法甚至不需要执行端口(在重命名时处理),因此归零 `xor` 和 `dec` 可以在同一周期内发送到乱序内核,并且`dec` 仍然能够在下一个循环中执行,就好像 `rdx` 没有被修改一样。无论如何,**缺点是前端的 2 uop 而不是 1 **。 (2认同)

Ale*_*nze 3

还有另一种 7 字节编码mov rdx, -1:48C7C2FFFFFFFF。

您可以尝试按照代码中的方式编写指令mov rdx, dword -1,以帮助编译器/汇编器使用这种较短的编码。