2014-10-20 158 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適用於任何操作數大小。如果您可以在堆棧中使用臨時文件,則除非需要代碼大小和速度的平衡,否則保存/恢復版本可能更可取。

相關問題