找回密码
 欢迎注册
查看: 6150|回复: 1

[原创] 大整数乘法代码

[复制链接]
发表于 2015-12-3 14:28:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
x86上128位二进制乘法最快速算法征解这篇文章里,liangbch的程序是最快的,在我的电脑上却不能运行,十分不解。而liangbch在x86上128位二进制乘法最快速算法征解中102楼的程序在我的电脑上能运行,于是大喜,学习之。
这里就是学习102楼的汇编乘法习作。
      
      编译环境:Windows xp ,vc++6.0,debug模式。
      硬件设备:AMD Athlon(tm) II X2  250          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位十进制数。
   


  1. /* 特别声明:*result 要用到的存贮空间,是* left 和*right 两个乘数的空间之和的两倍。*/
  2. _declspec(naked)
  3. void Big_mul( unsigned int *result,
  4.          const unsigned int * const left,
  5.                  const unsigned int * const right,int LL,int LR)
  6. {
  7. #undef  BASE10000_MASK
  8. #define BASE10000_MASK 100000000
  9. #undef LEFT_REG
  10. #undef RIGHT_REG
  11. #undef RESULT_REG
  12. #define LEFT_REG        esi
  13. #define RIGHT_REG        edi
  14. #define RESULT_REG        ebp       
  15.         __asm
  16.         {
  17.         push        esi
  18.         push        edi
  19.         push        ebx
  20.         push        ebp
  21. /*/------------------------------------------------------////
  22.       以上push语句原文如此,改一个都不行
  23. //------------------------------------------------------*////
  24.         mov        RIGHT_REG, dword ptr[esp +  0Ch+16]   
  25.         mov        ebx,dword ptr[esp+14h+16]     
  26. loop01:
  27.         mov        eax,dword ptr[esp+14h+16]
  28.         sub        eax,ebx
  29.                
  30.         mov        ecx,dword ptr[esp+10h+16]     ; //ecx中的值是内循环的次数,每次进入内循环时取新值。
  31.         mov        LEFT_REG,  dword ptr [esp + 08h+16]   ; // LEFT--REGk中的值是内循环的乘数,每次进入内循环时取新值。
  32.         mov        RESULT_REG, dword ptr[esp + 04h+16]   ; //RESULT_REG,结果,每次进入内循环时移位,
  33.         lea        RESULT_REG,[RESULT_REG+8*eax]
  34. loop00:
  35.         mov        eax,dword ptr [LEFT_REG]
  36.         mul        dword ptr [RIGHT_REG]
  37.                
  38.         add        dword ptr [RESULT_REG],eax
  39.         adc        dword ptr [RESULT_REG+4],edx
  40.         
  41.         lea        LEFT_REG,[LEFT_REG+4]
  42.         lea        RESULT_REG,[RESULT_REG+8]
  43.         dec        ecx
  44.         jnz        loop00;;///内循环。

  45.         lea        RIGHT_REG,[RIGHT_REG+4]
  46.         dec        ebx
  47.         jnz        loop01///////外循环
  48. /*/------------------------------------------------------------------------------------------------------------////
  49.    以上的loop00和loop01循环就是模拟手算的硬乘法。不考虑进位。
  50.    其中:第i列由RIGHT_REG[8*i]和RIGHT_REG[8*i+4]保存中间结果。
  51.    由于两个存贮单元只能存贮64位二进制数。故本函数要求输入的两个十进制乘数
  52.    不能同时超过14700位。
  53. //-----------------------------------------------------------------------------------------------------------*////
  54.         xor        edx,edx
  55.         mov        ebx,BASE10000_MASK
  56.         mov        ecx,dword ptr [esp + 10h+16]
  57.         add        ecx,dword ptr [esp + 14h+16]
  58.         mov        RESULT_REG, dword ptr[esp + 04h+16]   ; result
  59. loop02:
  60.         mov        eax,dword ptr [RESULT_REG+4]  ///取本位的高位做除法
  61.         div        ebx

  62.         add        dword ptr [RESULT_REG+12],eax///商加在下一个数的高位
  63.        
  64.         mov        eax, dword ptr [RESULT_REG]  ///取本位数的低位,做除法
  65.         div        ebx

  66.         mov        dword ptr [RESULT_REG],edx  ///本位的余数 就是结果。
  67.         xor        edx,edx
  68.         add        dword ptr [RESULT_REG+8],eax ///本位的商,加在下一位上面
  69.         adc        dword ptr [RESULT_REG+12],edx
  70.                
  71.         lea        RESULT_REG, [RESULT_REG+8]
  72.         sub        ecx,1
  73.         jnz        loop02
  74. /*/---------------------------------------------------------------------------------------------------------------------------------------///
  75.   以上loop02语句是将第i列RIGHT_REG[8*i]和RIGHT_REG[8*i+4]保存的中间结果。进位到第i+1列。
  76. //---------------------------------------------------------------------------------------------------------------------------------------*///
  77.         mov        ecx,dword ptr [esp + 10h+16]
  78.         add        ecx,dword ptr [esp + 14h+16]
  79.         mov        edx,1
  80.         xor        ebx,ebx
  81.         mov        RESULT_REG, dword ptr[esp + 04h+16]   ; result
  82. loop03:
  83.         mov       eax, dword ptr [RESULT_REG+8*edx]
  84.         mov       dword ptr [RESULT_REG+4*edx],eax
  85.         mov       dword ptr[RESULT_REG+8*edx],ebx
  86.         mov       dword ptr[RESULT_REG+8*edx+4],ebx
  87.         add       edx,1
  88.         sub       ecx,1
  89.         jnz       loop03
  90. /*/----------------------------------------------------------------------------------------////
  91.     以上loop03循环语句将结果移动到正常位置,并将多余的数清零。               
  92. //*--------------------------------------------------------------------------------------*////
  93.         pop        ebp
  94.         pop        ebx
  95.         pop        edi
  96.         pop        esi
  97. /*/------------------------------------------------------////
  98.       以上pop语句原文如此,改一个都不行
  99. //------------------------------------------------------*////
  100.         ret
  101.         }
  102. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2015-12-3 15:05:42 | 显示全部楼层
这里给出1楼函数的一个调用示例:
  

  1. #include <stdio.h>
  2. #define NA 14700
  3. char a[1500000]={0},b[1500000]={0};
  4. unsigned int c[10000]={0},e[10000]={0},result[40001]={0};
  5. int main()
  6. {
  7. void Big_mul( unsigned int *result,
  8.          const unsigned int * const left,
  9.                  const unsigned int * const right,int LL,int LR);
  10.         int i,s,m1,m2;       
  11.       // c[]=3014720201400230214565;
  12.      // e[]=999999926201254508952102;
  13. //计算c[]xe[]
  14.                 c[0]=30214565;
  15.                 c[1]=2014002;
  16.                 c[2]=301472;
  17.                 e[0]=8952102;
  18.                 e[1]=62012545;
  19.                 e[2]=99999992;
  20.         m1=3;
  21.         m2=3;
  22.                 Big_mul(result,c,e,m1,m2);///
  23.               i=m1+m2+5;
  24.                  while((result[i]==0)&&(i>0))//前导零清除。
  25.                          {
  26.                                  i--;
  27.                          }      
  28.                 printf("%u",result[i]);//输出语句。把乘积的结果输出。
  29.                 for(s=i-1;s>=0;s--)//输出语句。把乘积的结果输出。
  30.                         printf("%08u",result[s]);//输出语句。

  31.                 printf("\n");
  32.    
  33.   
  34.    

  35. return 0;
  36. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-20 21:43 , Processed in 0.043693 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表