大整数乘法代码
在x86上128位二进制乘法最快速算法征解这篇文章里,liangbch的程序是最快的,在我的电脑上却不能运行,十分不解。而liangbch在x86上128位二进制乘法最快速算法征解中102楼的程序在我的电脑上能运行,于是大喜,学习之。这里就是学习102楼的汇编乘法习作。
编译环境:Windows xp ,vc++6.0,debug模式。
硬件设备:AMD Athlon(tm) II X2250 3.0GHz 2.00G的内存
运行时间:两个14700位(十进制)数相乘,用时<5毫秒。
函数原形: void Big_mul( UINT32 *result,const UINT32 * const left,const UINT32 * const right,int LL,int LR)
其中:*result 乘积的结果。 * left 乘数。*right 另一个乘数。LL, *left的长度,LR, *right的长度。
进制:采用10000 0000进制。十进制数高位对应数组较大的下标,十进制数的低位对应数组较小的下标。
特别声明:*result 要用到的存贮空间,是* left 和*right 两个乘数的空间之和的两倍。
* left 和*right 两个乘数的长度不能同时超过14700位十进制数。
/* 特别声明:*result 要用到的存贮空间,是* left 和*right 两个乘数的空间之和的两倍。*/
_declspec(naked)
void Big_mul( unsigned int *result,
const unsigned int * const left,
const unsigned int * const right,int LL,int LR)
{
#undefBASE10000_MASK
#define BASE10000_MASK 100000000
#undef LEFT_REG
#undef RIGHT_REG
#undef RESULT_REG
#define LEFT_REG esi
#define RIGHT_REG edi
#define RESULT_REG ebp
__asm
{
push esi
push edi
push ebx
push ebp
/*/------------------------------------------------------////
以上push语句原文如此,改一个都不行
//------------------------------------------------------*////
mov RIGHT_REG, dword ptr
mov ebx,dword ptr
loop01:
mov eax,dword ptr
sub eax,ebx
mov ecx,dword ptr ; //ecx中的值是内循环的次数,每次进入内循环时取新值。
mov LEFT_REG,dword ptr ; // LEFT--REGk中的值是内循环的乘数,每次进入内循环时取新值。
mov RESULT_REG, dword ptr ; //RESULT_REG,结果,每次进入内循环时移位,
lea RESULT_REG,
loop00:
mov eax,dword ptr
mul dword ptr
add dword ptr ,eax
adc dword ptr ,edx
lea LEFT_REG,
lea RESULT_REG,
dec ecx
jnz loop00;;///内循环。
lea RIGHT_REG,
dec ebx
jnz loop01///////外循环
/*/------------------------------------------------------------------------------------------------------------////
以上的loop00和loop01循环就是模拟手算的硬乘法。不考虑进位。
其中:第i列由RIGHT_REG和RIGHT_REG保存中间结果。
由于两个存贮单元只能存贮64位二进制数。故本函数要求输入的两个十进制乘数
不能同时超过14700位。
//-----------------------------------------------------------------------------------------------------------*////
xor edx,edx
mov ebx,BASE10000_MASK
mov ecx,dword ptr
add ecx,dword ptr
mov RESULT_REG, dword ptr ; result
loop02:
mov eax,dword ptr ///取本位的高位做除法
div ebx
add dword ptr ,eax///商加在下一个数的高位
mov eax, dword ptr ///取本位数的低位,做除法
div ebx
mov dword ptr ,edx///本位的余数 就是结果。
xor edx,edx
add dword ptr ,eax ///本位的商,加在下一位上面
adc dword ptr ,edx
lea RESULT_REG,
sub ecx,1
jnz loop02
/*/---------------------------------------------------------------------------------------------------------------------------------------///
以上loop02语句是将第i列RIGHT_REG和RIGHT_REG保存的中间结果。进位到第i+1列。
//---------------------------------------------------------------------------------------------------------------------------------------*///
mov ecx,dword ptr
add ecx,dword ptr
mov edx,1
xor ebx,ebx
mov RESULT_REG, dword ptr ; result
loop03:
mov eax, dword ptr
mov dword ptr ,eax
mov dword ptr,ebx
mov dword ptr,ebx
add edx,1
sub ecx,1
jnz loop03
/*/----------------------------------------------------------------------------------------////
以上loop03循环语句将结果移动到正常位置,并将多余的数清零。
//*--------------------------------------------------------------------------------------*////
pop ebp
pop ebx
pop edi
pop esi
/*/------------------------------------------------------////
以上pop语句原文如此,改一个都不行
//------------------------------------------------------*////
ret
}
}
这里给出1楼函数的一个调用示例:
#include <stdio.h>
#define NA 14700
char a={0},b={0};
unsigned int c={0},e={0},result={0};
int main()
{
void Big_mul( unsigned int *result,
const unsigned int * const left,
const unsigned int * const right,int LL,int LR);
int i,s,m1,m2;
// c[]=3014720201400230214565;
// e[]=999999926201254508952102;
//计算c[]xe[]
c=30214565;
c=2014002;
c=301472;
e=8952102;
e=62012545;
e=99999992;
m1=3;
m2=3;
Big_mul(result,c,e,m1,m2);///
i=m1+m2+5;
while((result==0)&&(i>0))//前导零清除。
{
i--;
}
printf("%u",result);//输出语句。把乘积的结果输出。
for(s=i-1;s>=0;s--)//输出语句。把乘积的结果输出。
printf("%08u",result);//输出语句。
printf("\n");
return 0;
}
页:
[1]