有人知道如何在不使用其他变量,寄存器,堆栈或任何其他存储位置的情况下交换2个寄存器的值吗?谢谢!
像交换AX,BX。
答案 0 :(得分:2)
如果您真的需要交换两个注册表, xchg ax, bx
是大多数情况下所有现代CPU上最有效的方法。 (您可以构建一个案例,其中多个单uop指令可能更有效,因为由于周围代码导致一些其他奇怪的前端效应。或者对于32位操作数大小,其中零延迟mov
使得3 -mov序列在Intel CPU上具有更好的临时寄存器。)
对于代码大小,xchg-with-ax仅占用一个字节。这是0x90 NOP编码来自的地方:它是xchg ax,ax
或32位模式下的xchg eax,eax
。在64位模式下,xchg eax,eax
会将RAX截断为32位,因此0x90
显式为NOP指令,不也为xchg
。交换任何其他寄存器对xchg r, r/m
编码需要2个字节。 (如果在64位模式下需要,则为+ REX前缀。)
在实际的8086上,代码获取通常是性能瓶颈,因此xchg
是远的最佳方式,尤其是使用单字节xchg
- -AX简短形式。
对于32位/ 64位寄存器,带有临时值的3 mov
条指令可以从当前英特尔CPU上xchg
的移位消除中受益。 xchg
在英特尔上是3 uops,所有这些都有1c延迟并且需要一个执行单元,所以一个方向有2c延迟但另一个有1c延迟。有关当前CPU如何实现它的更多微体系结构详细信息,请参阅Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?。
在AMD Ryzen上,32/64位regs上的xchg
为2 uop并在重命名阶段处理,因此它类似于并行运行的两条mov
指令。在早期的AMD CPU上,它仍然是一个2 uop指令,但单向延迟为1c。
xor-swaps或add / sub swaps或mov
以外的任何其他多指令序列与寄存器的xchg
相比毫无意义。它们都有2个和3个周期延迟,以及更大的代码大小。唯一值得考虑的是mov
指令。
或者更好的是,展开循环或重新排列代码以便不需要交换,或只需要mov
。
请注意,带有内存的xchg
具有隐含的lock
前缀。 不使用xchg
内存,除非性能根本不重要,但代码大小确实如此。 (例如在引导程序中)。或者,如果你需要原子和/或完整的内存屏障,因为它们都是。
如果您需要使用内存交换寄存器而无法使用暂存寄存器,则xor-swap实际上可能是最佳选择。使用临时存储器需要复制存储器值(例如,使用push [mem]
复制到堆栈,或者在加载+存储内存操作数之前首先将寄存器溢出到第二个临时存储器位置。)
到目前为止,最低延迟方式仍然是临时寄存器;通常你可以选择不在关键路径上,或者只需要重新加载(不是首先保存,因为值已经在内存中或者可以从ALU的其他寄存器中重新计算指令)。
; spill/reload another register
push edx ; save/restore on the stack or anywhere else
movzx edx, word [mem] ; or just mov dx, [mem]
mov [mem], ax
mov eax, edx
pop edx ; or better, just clobber a scratch reg
使用寄存器交换内存的另外两个合理(但更糟糕的)选项是:不接触任何其他寄存器(SP除外):
; using scratch space on the stack
push [mem] ; [mem] can be any addressing mode, e.g. [bx]
mov [mem], ax
pop ax ; dep chain = load, store, reload.
或不接触任何其他内容:
; using no extra space anywhere
xor ax, [mem]
xor [mem], ax ; read-modify-write has store-forwarding + ALU latency
xor ax, [mem] ; dep chain = load+xor, (parallel load)+xor+store, reload+xor
使用两个内存目标xor
和一个内存源会导致更糟糕的吞吐量(更多存储和更长的依赖链)。
push / pop版本仅适用于可以推送/弹出的操作数大小,但xor-swap适用于任何操作数大小。如果您可以在堆栈上使用临时版,则可能更喜欢保存/恢复版本,除非您需要平衡代码大小和速度。
答案 1 :(得分:-1)
您可以使用一些数学运算来完成。我可以给你一个主意。希望它有所帮助!
我已遵循此C代码:
int i=10; j=20
i=i+j;
j=i-j;
i=i-j;
mov ax,10
mov bx,20
add ax,bx
//mov command to copy data from accumulator to ax, I forgot the statement, now ax=30
sub bx,ax //accumulator vil b 10
//mov command to copy data from accumulator to bx, I forgot the statement now
sub ax,bx //accumulator vil b 20
//mov command to copy data from accumulator to ax, I forgot the statement now