我需要一些簡單的方法來在x86彙編程序中劃分64b無符號整數。我的號碼保存在兩個32b寄存器EDX:EAX中,我需要將結果返回給EDX:EAX。因子是32b整數。請問一些代碼?彙編程序64b部門
3
A
回答
5
如果我正確解釋你的問題(特別是部分Factor is in 32b integer
),你希望將64位除數除以32位除數並得到64位商數。
如果這種解釋是正確的,那麼在32位代碼中實際上很容易。
這個想法是,你除以除數的兩半的「紅利」,並重新使用第一師的剩餘部分作爲第二師。
C代碼示出了如何做到這一點:
#include <stdio.h>
#include <limits.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned int uint32;
#else
typedef unsigned long uint32;
#endif
typedef unsigned long long uint64;
typedef unsigned long ulong;
// Make sure uint32=32 bits and uint64=64 bits
C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);
C_ASSERT(sizeof(uint64) * CHAR_BIT == 64);
int div64by32eq64(uint64* dividend, uint32 divisor)
{
uint32 dividendHi = (uint32)(*dividend >> 32);
uint32 dividendLo = (uint32)*dividend;
uint32 quotientHi;
uint32 quotientLo;
if (divisor == 0)
return 0;
// This can be done as one 32-bit DIV, e.g. "div ecx"
quotientHi = dividendHi/divisor;
dividendHi = dividendHi % divisor;
// This can be done as another 32-bit DIV, e.g. "div ecx"
quotientLo = (uint32)((((uint64)dividendHi << 32) + dividendLo)/divisor);
*dividend = ((uint64)quotientHi << 32) + quotientLo;
return 1;
}
int main(void)
{
static const struct
{
uint64 dividend;
uint32 divisor;
} testData[] =
{
{ 1 , 0 },
{ 0xFFFFFFFFFFFFFFFFULL, 1 },
{ 0xFFFFFFFFFFFFFFFFULL, 2 },
{ 0xFFFFFFFF00000000ULL, 0xFFFFFFFFUL },
{ 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFUL },
};
int i;
for (i = 0; i < sizeof(testData)/sizeof(testData[0]); i++)
{
uint64 dividend = testData[i].dividend;
uint32 divisor = testData[i].divisor;
printf("0x%016llX/0x%08lX = ", dividend, (ulong)divisor);
if (div64by32eq64(÷nd, divisor))
printf("0x%016llX\n", dividend);
else
printf("division by 0 error\n");
}
return 0;
}
輸出(ideone):
0x0000000000000001/0x00000000 = division by 0 error
0xFFFFFFFFFFFFFFFF/0x00000001 = 0xFFFFFFFFFFFFFFFF
0xFFFFFFFFFFFFFFFF/0x00000002 = 0x7FFFFFFFFFFFFFFF
0xFFFFFFFF00000000/0xFFFFFFFF = 0x0000000100000000
0xFFFFFFFFFFFFFFFF/0xFFFFFFFF = 0x0000000100000001
而現在在組件(NASM語法),而不由0除法檢查等效劃分代碼:
; 64-bit dividend
mov edx, 0xFFFFFFFF
mov eax, 0xFFFFFFFF
; 32-bit divisor
mov ecx, 0xFFFFFFFF
push eax
mov eax, edx
xor edx, edx
div ecx ; get high 32 bits of quotient
xchg eax, [esp] ; store them on stack, get low 32 bits of dividend
div ecx ; get low 32 bits of quotient
pop edx ; 64-bit quotient in edx:eax now
; edx:eax should now be equal 0x0000000100000001
0
0
快速術語概括:分子/除數=結果+餘數/除數
首先檢查如果除數爲零(中止如果它是)。
test eax,eax
jne .ok
test edx,edx
je .divisionByZero
.ok:
移位除數留到MSB,同時保持跟蹤有多少班次你沒有設置:
xor ebp,ebp ;ebp = bits shifted so far
test edx,(1 << 31)
jne .l2
.l1:
shld edx,eax,1
shl eax,1
inc ebp
test edx,(1 << 31)
jne .l1
.l2:
將當前結果爲零:
xor esi,esi
xor edi,edi
現在轉移除數回到原來的位置;而從在結果剩餘的分子和設置一個位減去當前除數每當當前除數小於當前分子:
.nextBit:
shld edi,esi,1
shl esi,1
cmp ecx,edx
jb .doneBit
ja .subtract
cmp ebx,eax
jb .doneBit
.subtract:
sub ecx,edx
sbb ebx,eax
or esi,1
.doneBit:
sub ebp,1
jnc .nextBit
此時EDX:EAX是相同的值是,EDI:ESI是結果和ECX:剩下的就是EBX。
警告:以上所有內容均未經過測試。這只是一個例子/描述。
注:如果數字有符號,您需要首先從分子和除數中刪除符號位;然後在結果中設置符號位並在後面設置餘數(sign = numerator_sign XOR divisor_sign
)。
相關問題
- 1. 彙編:16位部門
- 2. 「彙編」與「彙編程序」
- 3. 彙編x86部門fpoint異常
- 4. 彙編程序
- 5. 彙編語言入門視頻教程?
- 6. 按部門彙總有條件匯票
- 7. 彙編語言程序中的部分
- 8. 彙編8086程序
- 9. NASM彙編程序
- 10. 彙編:編譯COM程序
- 11. 微軟彙編程序轉換爲GNU彙編程序
- 12. 程序的彙編和執行 - 兩遍彙編程序
- 13. 忽略彙編程序函數的彙編程序關鍵字
- 14. SIC彙編程序I/O
- 15. 不明白彙編程序
- 16. 問題彙編C++程序
- 17. LC3彙編語言程序
- 18. Actionscript 3彙編程序
- 19. Jena tdbloader彙編程序
- 20. c#彙編程序dll
- 21. 彙編程序安裝
- 22. 彙編語言子程序
- 23. C++中的彙編程序
- 24. 彙編程序問題
- 25. BubbleSort與彙編程序
- 26. 彙編程序:遞歸?
- 27. 第一個彙編程序
- 28. windows x64彙編程序?
- 29. 運行彙編程序
- 30. 16位彙編程序
只是爲了澄清,你的意思是否使用x64指令?也就是說,這只是將數據轉化爲64位寄存器(例如RAX),進行64位分割,然後將它們分割回32位寄存器,或者您是否想要在32位處理器上模擬64位分割? – WeirdlyCheezy
沒有64b reg - 我試圖在32b上模擬64b分區。 – Nick
如果是這樣的話,這聽起來像你基本上從幾乎從零開始執行二進制分割。對於SO問題,這看起來有點寬泛。你試過什麼了?有沒有一個更具體的部分你堅持? – WeirdlyCheezy