为什么可以在ARMv8上使用xzr寄存器而不是文字0?

时间:2017-03-14 14:27:26

标签: assembly arm armv8

我正在阅读来自ARM的SVE whitepaper并遇到一些令我感到奇怪的事情(在非SVE示例中):

xzr

我不知道这个x8注册是什么,所以我查了一下,发现some content from ARM说明在许多情况下,它是零的同义词。

所以看起来x8被初始化为零,这是有道理的,因为它是在0用作循环计数器的循环之前执行的。

我不明白的是,为什么不使用文字xzr代替mov x8, 0 ?例如:

xzr

总结一下,我的问题是:为什么可以在这里使用0注册而不是文字org.springframework.security.authentication.AccountStatusUserDetailsChecker

5 个答案:

答案 0 :(得分:4)

我认为mov x8, xzr vs mov x8, #0比较是一种红色的鲱鱼。

正如@ old_timer的答案显示的那样,没有编码收益,而且很可能(虽然我没有检查过)很少或没有管道性能提升。

xzr给我们的是 - 除了@InninitelyManic的答案之外的虚拟寄存器 - 是访问零值操作数而无需加载和占用实际寄存器。这样可以获得少一个指令的双重好处,还有一个寄存器可用于保存“真实”指令。数据

我认为这是原始'some content from ARM' referred to in the OP忽略指出的一个重要特征。

我的意思是mov x8, xzr vs mov x8, #0是红鲱鱼。如果我们将x8归零以便随后修改它,那么使用xzr#0非常随意(尽管我倾向于{{1} }更明显)。但是,如果我们将#0纯粹归零以便为后续指令提供零操作数,那么我们最好还是使用 - 在允许的地方 - x8而不是{{1} }作为 指令中的操作数,而不是归零xzr

答案 1 :(得分:2)

mov x8,xzr
mov x8,#0
mov x8,0

产生

0000000000000000 <.text>:
   0:   aa1f03e8    mov x8, xzr
   4:   d2800008    mov x8, #0x0                    // #0
   8:   d2800008    mov x8, #0x0                    // #0

除了允许立即没有英镑符号之外,没有其他真正的惊喜。这不是一个指令大小问题(同样毫不奇怪,x86例如xor rax,rax比mov rax便宜,0),也许有一个管道性能增益(尽管流行的信念指令需要多个时钟开始完成)

最有可能是个人偏好我们有这个很酷的mips,就像总是零注册的东西,让我们只是为了好玩。

答案 2 :(得分:0)

这两条指令应该是相同的 - 无论是效果还是预期的表现。

它们实际上是更多通用指令的别名

mov x8, 0编码为orr x8, xzr, 0

mov x8, xzr编码为orr x8, xzr, xzr

别名很有用,因为它们使ASM更具可读性。

第二种编码说明了为什么使用零寄存器xzr会很有用。因为我们知道xzr总是为零,所以我们可以重用orr的{​​{1}}指令。没有它,mov将需要不同的编码,因此会浪费编码空间。

答案 3 :(得分:0)

这个答案不是四十四岁四十四岁。对OP。

XZR可用于丢弃结果;例如,&#34; ldr xzr,[sp],16&#34;。见下面的GDB

0x7fffffef40:   0x00000000      0x00000000      0x00400498      0x00000000
0x7fffffef50:   0x00000000      0x00000000      0x00000000      0x00000000
              ldr x0,=0xdead
(gdb)
              ldr x1,=0xc0de
(gdb)
              stp x0, x1, [sp, #-16]!
(gdb) x/8x $sp
0x7fffffef30:   0x0000dead      0x00000000      0x0000c0de      0x00000000
0x7fffffef40:   0x00000000      0x00000000      0x00400498      0x00000000

              ldr xzr, [sp], #16
(gdb) x/8x $sp
0x7fffffef40:   0x00000000      0x00000000      0x00400498      0x00000000
0x7fffffef50:   0x00000000      0x00000000      0x00000000      0x00000000

还要记住,在ARMv8中,堆栈应该是四字对齐或SP mod 16 = 0。 所以你可以使用XZR中的一个&#34;推送&#34;或者&#34;弹出&#34;配对寄存器。

stp x1, xzr, [sp, #-16]!

ldp x10, xzr, [sp], #16

答案 4 :(得分:-1)

<强> TL; DR

将64位字面值加载到寄存器中需要多条指令,但只使用zxr将一条指令设置为0。因此代码更短更快。

要将文字移动到寄存器,您可以使用MOVL指令,请参阅臂参考:

  

MOVL伪指令

     

使用以下任一方式加载寄存器:

A 32-bit or 64-bit immediate value.

Any address.
     

MOVL生成两条或四条指令...... MOV,MOVK对。

因此,将文字加载到寄存器中是一个多步骤的过程。如果您只想清除寄存器,那么他们就有了快捷方式。 zxr是一个伪寄存器,它总是读取零,这是一个你需要的公共值,并且可以在一条指令中将寄存器移到寄存器。

在Microchip组装中,它们具有类似的概念。要将寄存器设置为文字,您可以执行以下操作:

MOVLW   10       (Move 10 to the working register) 
MOVWF   0x1234   (Move the working register to address 0x1234)

但要设置为零,他们会有指令:

CLRF    0x1234   (Set 0x1234 to zero)