我在空閒時間學習英特爾彙編語言(att語法),我只是想知道如何將兩個數字相乘,讓5和2可以不使用mul命令?x86彙編乘以兩個32位數
回答
除非你的CPU是有缺陷的莫名其妙,你只使用的mul
命令:-)
然而,在一般意義上,你只需要知道乘法重複此外,讓4 x 7
爲七很多四個加在一起:4 + 4 + 4 + 4 + 4 + 4 + 4
。
所以對於這樣的野獸簡單的僞代碼將是:
def mul(unsigned a, unsigned b): # line 1
res = 0 # line 2
while b > 0: # line 3
res = res + a # line 4
b = b - 1 # line 5
return res # line 6
在樣品試運行使用您的測試數據顯示了這一過程:
Line# a b res
----- --- --- ---
1 5 2 ?
2 0
3 (b>0, keep going)
4 5
5 1
3 (b>0, keep going)
4 10
5 0
3 (b==0, exit loop)
6 (returns 10)
請注意,這是使用無符號值,只需稍作修改即可處理帶符號的值:
def mul(int a, int b):
sign = 1
if a < 0:
a = -a
sign = -sign
if b < 0:
b = -b
sign = -sign
res = 0
while a > 0:
res = res + b
a = a - 1
if sign == -1:
res = -res
return res
此外請記住,實際上有更多的方法可以進行乘法運算,包括值的位移(最小化所需的加法運算),而不是簡單的重複加法。
由此我的意思是像9999 x 9999
這樣的計算將使用簡單的方法執行大約10,000次添加。通過使用班次,您可以將其中一個數字所需的添加數限制爲每個數字九位,而另一個數字則可以將每位數增加一位,這意味着您可以在上面的計算中添加約40個添加項。
希望這將讓感覺,當你意識到你可以簡化9999 x 9999
到:
9999 x 9 -> nine additions
+ 99990 x 9 -> nine additions
+ 999900 x 9 -> nine additions
+ 9999000 x 9 -> nine additions
\____________/
|
V
three additions
如果你想看到更詳細換擋作品,維基百科有一個article on the topic。
順便說一句,你可以乘以常數時,因爲你提前知道行動需要進行哪些得到相當不錯的性能。例如,十乘以寄存器可以用像做(請記住我的組裝日子已經過去長):
mul_ax_by_10: push bx ; save registers
shl ax ; ax <- orig_ax * 2
push ax ; save for later add
shl ax
shl ax ; ax <- orig_ax * 8
pop bx ; bx <- orig_ax * 2
add ax, bx ; ax <- (orig_ax * 8) + (orig_ax * 2)
; <- orig_ax * (8 + 2)
; <- orig_ax * 10
pop bx ; restore saved register
ret ; result in ax
由於您所標記的問題與c,我假設你疲於應付GCC的內聯彙編程序。
在舊的十進制日期中,您進行了乘法 - 例如, 11 * 14 - 如下:
你把乘數(11)= 1的最右邊的數字,並與被乘數乘以它(14)= 14
你拍了下位左乘數= 1,乘以乘數= 14並將結果小數點左移一位數= 140.您也可以移位被乘數而不是結果:1 * 140 = 140。
您加入的結果,最終的結果是:14 + 140 = 154
這種算法也是binarism的勇敢新世界有效:
就拿最右邊(乘法器)(1110b)乘以乘法器(1011b)的乘法運算結果位。這不是一個真正的乘法。您只有兩個選項:0 * 1110b = 0和1 * 1110b = 1110b。結果是根據位0或被乘數。將其添加到最終結果。
如果乘數大於零,則下一位等待乘數中最右邊的位。移位被乘數由一個比特的左(在以上步驟2中的第二個選項)和轉到步驟1.
的GCC程序:
#include <stdio.h>
unsigned mul (unsigned multiplier, unsigned multiplicand)
{
unsigned r = 0;
while (multiplier)
{
if (multiplier & 1) r += multiplicand;
multiplier >>= 1;
multiplicand <<= 1;
}
return r;
}
unsigned mul_asm (unsigned multiplier, unsigned multiplicand)
{
unsigned result = 0;
asm
(
"movl %[multiplier], %%edx;" // EDX = multiplier
"movl %[multiplicand], %%ecx;" // ECX = multiplicand
"xorl %%eax, %%eax;" // Result = 0
"L1:;" // While-loop
"shrl $1, %%edx;" // Get rightmost bit of the multiplier
"jnc 1f;" // Skip the next line if this bit == 0
"leal (%%ecx,%%eax), %%eax;" // Add multiplicand to result (without changing flags)
"1:;" // Local jump label
"leal (,%%ecx,2), %%ecx;" // Shift multiplicand left by one bit (without changing flags)
"jnz L1;" // While EDX != 0 (zero flag from the shrl-line)
"movl %%eax, %[result];" // Return value
: [result] "=m" (result) // Output
: [multiplier] "m" (multiplier), // Input
[multiplicand] "m" (multiplicand)
: "%eax", "%ecx", "%edx", "cc" // Clobbered registers & flags
);
return result;
}
int main (void)
{
unsigned result, multiplier, multiplicand;
multiplier = 17;
multiplicand = 23;
result = multiplier * multiplicand;
printf ("direct: %u * %u = %u\n", multiplier, multiplicand, result);
result = mul (multiplier,multiplicand);
printf ("mul: %u * %u = %u\n", multiplier, multiplicand, result);
result = mul_asm (multiplier,multiplicand);
printf ("mul_asm: %u * %u = %u\n", multiplier, multiplicand, result);
return 0;
}
- 1. 4位乘以8位彙編乘法
- 2. 彙編i8080乘以兩個16位數字
- 3. 在8086微處理器上乘以32位兩個數字
- 4. 如何在MIPS中乘以兩個大於32位的整數?
- 5. 32位Linux x86彙編代碼和垃圾在輸出
- 6. 追加兩個String在x86彙編
- 7. 32位Linux彙編代碼
- 8. 是否有可能在x86彙編中立即乘以mul?
- 9. 用於在32位機器上添加兩個64位數的彙編宏
- 10. POPF x86彙編
- 11. 使用32位x86 AT&T彙編調用C函數的問題
- 12. 'atltime.h錯誤32位彙編詩句64位彙編
- 13. 使用相對指針尋址數據(x86-32彙編程序)
- 14. 乘以兩位小數
- 15. 的彙編參數(X86,ATT)
- 16. 解密x86彙編函數
- 17. x86彙編比較參數
- 18. x86彙編轉換基數
- 19. 乘以兩個32位數字......這個代碼有什麼問題
- 20. 兩個32位有符號整數使用SSE2相乘
- 21. x86彙編語言
- 22. x86-64 GNU彙編
- 23. 功率x86彙編
- 24. x86彙編錯誤
- 25. x86彙編添加
- 26. x86彙編代碼
- 27. 彙編程序將兩個32位數字,並在屏幕上顯示結果
- 28. x 86彙編語言:移位乘以64位答案
- 29. 有沒有辦法在JavaScript中正確乘以兩個32位整數?
- 30. 獨立的32位彙編程序
既然你有2的倍數那裏,您可以使用左移,右移多次/除以2或2的倍數。 – dawg
嗨,傑克,如果你想在ASM的答案,考慮使用[彙編標籤](http://stackoverflow.com/questions/tagged/assembly)而不是[c tag](http://stackoverflow.com/questions/tagged/c)... – Myst
你也可以使用'imul'。或者'aad'。 – fuz