【问题标题】:What is the purpose of xorps on the same register?xorps 在同一个寄存器上的目的是什么?
【发布时间】:2016-01-30 15:51:25
【问题描述】:

我正在查看以下反汇编的 c++ 代码

    auto test2 = convert<years, weeks>(2.0);
00007FF6D6475ECC  mov         eax,16Dh  
00007FF6D6475ED1  xorps       xmm1,xmm1  
00007FF6D6475ED4  cvtsi2sd    xmm1,rax  
00007FF6D6475ED9  mulsd       xmm1,mmword ptr [__real@4000000000000000 (07FF6D64AFE38h)]  
00007FF6D6475EE1  divsd       xmm1,mmword ptr [__real@401c000000000000 (07FF6D64AFE58h)] 

并对xorps xmm1, xmm1 指令的意义感到好奇。似乎任何数字 xor 本身只会给出 0?如果有,清零的目的是什么?

注意:我只是出于好奇而问这个问题。我对汇编语言知之甚少。

【问题讨论】:

  • 是的,快速将 xmm1 中的所有位设置为 0 是本意。 cvtsi2sd 指令只分配位 0..63
  • @HansPassant 啊,这是像“c++ double(64 位)实际上只是 x64 架构上的单精度浮点数”之类的工件吗?我也有点想知道为什么单精度乘法/除法被用于双精度数。
  • @NicolasHolthaus:它是一个 scalar 64b 双精度变量,在一个足够宽的寄存器中进行操作,可以将两个双精度值打包在一起。 (mulPd/divPd.)

标签: c++ assembly


【解决方案1】:

XMM 寄存器有 128 位,使用cvtsi2sd 只会填满低 64 位。因此,xorps 指令用于清除可能影响后续操作的垃圾值和/或依赖链。

基本上,您的操作顺序是:

mov         eax, 16Dh       ; load 0x16D into lower 32 bits of RAX register
xorps       xmm1, xmm1      ; zero xmm1
cvtsi2sd    xmm1, rax       ; load lower 32 bits from RAX into xmm1
<do more stuff with xmm1>

当只加载后续指令在其全部范围内运行的寄存器的一部分时,在汇编中将寄存器归零的必要性非常频繁。执行xor x, x 是一种常见的寄存器清除模式。

另请参阅this(非常详尽且非常棒,根据 cmets)答案,了解为什么 xor 比其他替代方案更受欢迎(mov x, 0and x, 0)的更多详细信息。

【讨论】:

  • 使用异或归零的大多数更微妙的原因仅适用于整数寄存器(请参阅我在stackoverflow.com/questions/33666617/… 的回答),但不消耗执行单元或物理寄存器文件条目(Intel SnB -family)仍然适用。此外,对于向量 reg,没有 mov-immediate 形式。如果有vpbroadcastd v, imm32 可能会很好,但没有。你说得对,xorpspsubd same,same 更好,不过。概率。一些 CPU 不会破坏 psub 的 dep 链。
  • 另外,在这种情况下,首先清除 reg 可能更多是为了打破对 xmm1 先前值的依赖。只要代码仅使用进一步的标量指令,而不是 ... PD(打包双),upper64 中的垃圾就不会导致减速或故障。每条指令都有一个标量版本(当然除了随机播放)。
  • 这两个链接都只是链接到问题,而我认为您打算链接到某些答案。
  • @Puppy:如果你说的是我的链接:是的,我说的是我在上面写的答案。我链接到这个问题,因为它很短,并且提供了答案正在回复的上下文。此外,我有时会觉得与我的答案而不是 OP 的问题相关联有点自大。我不认为 Zdeněk 选择的答案是最好的,顺便说一句。我不得不对此发表评论。
  • @PeterCordes 已修复 :)
猜你喜欢
  • 1970-01-01
  • 2020-12-24
  • 2019-04-11
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 2020-09-14
相关资源
最近更新 更多