簡體   English   中英

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

[英]Why might one use the xzr register instead of the literal 0 on ARMv8?

我正在閱讀來自ARM的SVE白皮書 ,並遇到了一些令我感到奇怪的事情(在非SVE示例中):

mov x8, xzr

我不知道這個xzr寄存器是什么,所以我xzr了一下,發現ARM的一些內容 ,說它在很多情況下都是零的同義詞。

所以看起來x8被初始化為零,這是有道理的,因為它是在一個循環之前執行的,其中x8被用作循環計數器。

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

mov x8, 0

總而言之,我的問題是:為什么可以在這里使用xzr寄存器而不是文字0

我認為mov x8, xzr vs mov x8, #0比較是一個紅色的鯡魚。

正如@ old_timer的回答所示,沒有編碼增益,很可能(雖然我沒有檢查)很少或沒有管道性能增益。

然而, xzr給我們的是 - 除了xzr的答案之外的虛擬寄存器 - 是訪問零值操作數而無需加載和占用實際寄存器 這具有一個較少指令的雙重好處,並且還有一個寄存器可用於保存“真實”數據。

我認為這是一個重要的特征, OP中提到的原始“來自ARM的一些內容”忽略了指出。

這就是我的意思是mov x8, xzr vs mov x8, #0是一個紅色的鯡魚。 如果我們將x8零以便隨后修改它,那么使用xzr#0是非常隨意的(盡管我傾向於贊成#0更為明顯)。 但是,如果我們歸零x8 ,以提供一個零操作數后續指令純粹,那么,我們會更好用-如果允許- xzr而不是x8作為指令的操作數,而不是零x8的。

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,如總是零注冊的東西,讓我們只是為了好玩。

這兩條指令應該是相同的 - 在效果和預期性能方面。

它們實際上都是更多通用指令的別名

mov x8, 0 orr x8, xzr, 0被編碼為orr x8, xzr, 0

mov x8, xzr編碼為orr x8, xzr, xzr

別名很有用,因為它們使ASM更具可讀性。

第二種編碼說明了為什么使用零寄存器xzr會很有用。 因為我們知道xzr總是為零,所以我們可以重用movorr指令。 沒有它, mov將需要不同的編碼,因此會浪費編碼空間。

這個答案對OP來說並非“四肢着地”。

XZR可用於丟棄結果; 例如,“ldr xzr,[sp],16”。 見下面的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中的一個“推”或“彈出”對寄存器。

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

ldp x10, xzr, [sp], #16

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM