2016-04-28 49 views
1

所以這應該是一個很容易回答的問題。如何在程序集中添加和減去大型變量?

想我給出了兩個非常大的變數一個b,我想減b一個。假設每個變量都是30個字。我不能只使用sub指導員嗎?我被告知,它將默認爲sub.w,並且只會從a的第一個字中減去b的第一個單詞。

那麼我該怎麼做呢?

+3

閱讀關於adc和sbb的說明。 –

+2

你在用什麼CPU? –

回答

2

要執行多字減法,請從低位字開始,並從兩個變量中減去相應的字。使用sbb指令處理借位,並僅在第1次減法中使用sub

mov dx, [ebx]  ;First word of b 
sub [eax], dx  ;Subtract from 1st word of a 
mov dx, [ebx+2] ;Second word of b 
sbb [eax+2], dx ;Subtract from 2nd word of a 
mov dx, [ebx+4] ;Third word of b 
sbb [eax+4], dx ;Subtract from 3rd word of a 
... 
mov dx, [ebx+58] ;Thirtieth word of b 
sbb [eax+58], dx ;Subtract from 30th word of a 

一個更實際的解決方案使用一個循環:

mov ecx, 30 
xor esi, esi  ;This clears the CF, needed for the very first SBB 
Again: 
mov dx, [ebx+esi] 
sbb [eax+esi], dx 
lea esi, [esi+2] 
loop Again   ; loop without clobbering CF. 

better ways to write fast adc/sbb loops,但最優選擇的微架構之間變化。減少slowloop instruction開銷的一種簡單方法是展開一點。

mov ecx, 15 
xor esi, esi  ;This clears the CF, needed for the very first SBB 
Again: 
mov dx, [ebx+esi] 
sbb [eax+esi], dx 
mov dx, [ebx+esi+2] 
sbb [eax+esi+2], dx 
lea esi, [esi+4] 
loop Again 

在優化此任務下一步驟是停止使用16位寄存器DX,而要用較大的EDX寄存器。這會將完全展開版本中的指令數量減半,或者將循環版本中的迭代次數減半以上。我們可以這樣做,因爲「30個字長的變量」可以被認爲是「15個雙字長的變量」。

這是完全展開的版本:

mov edx, [ebx] ;First dword of b 
sub [eax], edx ;Subtract from 1st dword of a 
mov edx, [ebx+4] ;Second dword of b 
sbb [eax+4], edx ;Subtract from 2nd dword of a 
mov edx, [ebx+8] ;Third dword of b 
sbb [eax+8], edx ;Subtract from 3rd dword of a 
... 
mov edx, [ebx+56] ;Fifteenth dword of b 
sbb [eax+56], edx ;Subtract from 15th dword of a 

和部分展開循環版本:同樣使用RDX將進一步完善這些代碼

mov ecx, 5 
clc    ;This clears the CF, needed for the very first SBB 
Again: 
mov edx, [ebx] ; <1> 
sbb [eax], edx 
mov edx, [ebx+4] ; <2> 
sbb [eax+4], edx 
mov edx, [ebx+8] ; <3> 
sbb [eax+8], edx 
lea ebx, [ebx+12] 
lea eax, [eax+12] 
loop Again 

顯然對x86-64的。請注意,儘管30個單詞對應於7個單詞和1個單詞。

+0

添加和cmp clobber標誌。沒有「理想」的方式來執行多精度循環,因爲dec/jnz會導致部分標誌失速,而'循環'很慢。展開一下,使用笨重的東西有所幫助。 –

+0

@PeterCordes感謝您發現'add'和'cmp'破壞了標誌。我編輯了答案。 –

+0

你的編輯沒有強調循環而不用clobbering CF的事實是非平凡的。我做了一個編輯,無恥地鏈接到我自己的答案。隨意找到其他鏈接,比我更簡潔地解釋事情。我傾向於將自己的答案鏈接起來,因爲我記得它們存在並可以輕鬆找到它們。 :P –