2014-10-20 153 views
-1

某人是否知道如何交换的2个寄存器的值,而无需使用另一个变量,寄存器,堆栈,或任何其他存储的地址?谢谢!交换2个寄存器8086汇编语言(16位)

像换AX,BX。

+0

[XOR SWAP](http://en.wikipedia.org/wiki/XOR_swap_algorithm) – Michael 2014-10-20 15:23:35

+4

有一个'XCHG'指令... – Jester 2014-10-20 15:24:14

+0

http://felixcloutier.com/x86/XCHG.html – 2017-10-01 18:50:10

回答

-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 
+0

汇编代码到目前为止不代表C代码!而且,当AX为累加器时,为什么要将数据从累加器复制到ax **? – 2015-01-29 18:17:42

+1

为什么建议这样复杂的事情,当你只能使用xchg? – prl 2017-09-24 00:39:08

1

如果你真的需要换两个REG,xchg ax, bx在大多数情况下所有现代CPU的最有效方式。 (您可以构造一个案例,其中由于周围的代码会导致一些其他奇怪的前端效果,因此多个单一顶级指令可能会更有效;或者,对于32位操作数大小,其中零延迟mov使用3-mov序列英特尔CPU上的临时寄存器更好)。

对于代码大小XCHG-与斧只需要一个字节。这是0x90 NOP编码的来源:它的编号为xchg ax,axxchg eax,eax(32位模式)。在64位模式下,将xchg eax,eax RAX截断为32位,所以0x90是明确地一个NOP指令,也是一个xchg。交换其他任何一对寄存器需要2个字节用于xchg r, r/m编码。 (+如果需要REX前缀在64位模式下)。

在实际的8086,代码取为通常的性能瓶颈,所以xchg是由的最佳方式,特别是在使用单字节xchg - 与-AX短格式。


对于32位/ 64位寄存器,3 mov与临时指令可受益于MOV-消除其中xchg不能在当前英特尔CPU。 xchg在Intel上是3个uops,它们都有1c的延迟并需要执行单元,所以一个方向有2c延迟,但另一个有1c延迟。请参阅Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?了解更多关于当前CPU如何实现它的微架构细节。

对于AMD Ryzen,在32/64位regs上的xchg是2个uops,并且在重命名阶段处理,因此它就像两个并行运行的mov指令。在早期的AMD CPU上,它仍然是一个2 uop指令,但每路都有1c延迟。相比xchg为寄存器


XOR-互换或添加/子交换或大于mov其他任何其它多指令序列是没有意义的。它们都有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和一个内存源将会导致吞吐量变差(更多的存储和更长的依赖链)。

推/拉版本仅适用于可以推/拉的操作数大小,但xor-swap适用于任何操作数大小。如果您可以在堆栈中使用临时文件,则除非需要代码大小和速度的平衡,否则保存/恢复版本可能更可取。

相关问题