- 注册时间
- 2010-2-12
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 1214
- 在线时间
- 小时
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?欢迎注册
×
本帖最后由 只是呼吸 于 2016-12-11 02:26 编辑
在大整数的运算程序中,无符号加法应该算最容易写的了。但要把加法的运算程序尽可能运行快一点,仍然要动一番脑筋。
这个加法程序是我在本论坛学习的过程中,参照了管理员 liangbch 的两篇文章写成的。
http://bbs.emath.ac.cn/thread-216-11-1.html 在这篇文章的第102楼,学习了汇编语言的接口技术。
http://bbs.emath.ac.cn/thread-521-3-1.html 在这篇文章,学习了把单精度除法转化为乘法的技术。
下面是我写的大整数加法程序:
- /*
- * 声明:本函数的接口技术、单精度乘法代替单精度除法技术,学习自管理员liangbch的两篇帖子:http://bbs.emath.ac.cn/thread-216-11-1.html第102楼 和 http://bbs.emath.ac.cn/thread-521-3-1.html
- * liangbch依法享有著作权和解释权
- *\
- * dst: 目的数组,存放和。
- * src1: 第一个加数,(操作数)
- * src2: 第二个加数,(操作数)
- * size1; 第一个加数的长度。
- * size2: 第二个加数的长度。
- * 所有数组均采用10^8进制,数组较大的下标对应10进制数的高位,数组较小的下标对应10进制数的低位。
- */
- _declspec(naked)////这个程序能处理任意长度的两个无符号大整数之和,速度快。
- void big_add_ALU(unsigned long *dst,unsigned long *src1,unsigned long *src2,int size1,int size2)
- {
- #undef BASE10000_MASK
- #define BASE10000_MASK BASE
- _asm
- {
- push esi
- push edi
- push ebx
- push ebp
-
- mov edi, dword ptr [esp+0Ch+16]
- mov ebp, dword ptr [esp+04h+16]
- xor eax,eax
- mov ebx, BASE10000_MASK
- movd mm4,eax
- mov esi, dword ptr [esp+08h+16]
- mov eax, 0xabcc7712
- movd mm7,ebx
- movd mm5,eax
-
- xor ebx,ebx
- mov ecx, dword ptr [esp+14h+16]
- mov eax, dword ptr [esp+10h+16]
- cmp eax, ecx
- jl fffd
-
- jmp jjj
- fffd:
- mov ecx,eax // < 则跳转
- jjj:
-
- loop02:
-
- movd mm1, dword ptr [esi]
- movd mm2, dword ptr [edi]
-
- paddq mm1, mm2
- paddq mm1, mm4
-
- movq mm2, mm1 // mm2, 总和
- pmuludq mm1,mm5
- psrlq mm1,58
- movq mm4,mm1// mm4 进位
- pmuludq mm1,mm7
- psubq mm2,mm1
-
- movd dword ptr[ebp],mm2
- lea edi, dword ptr [edi+4]
- lea ebp, dword ptr [ebp+4]
- lea esi, dword ptr [esi+4]
-
- dec ecx
- jnz loop02
- //--------以上是公共部分之和------------------//
- mov ecx, dword ptr [esp+14h+16]
- mov eax, dword ptr [esp+10h+16]
- cmp eax,ecx
- je exit1
- jl fffdd
- sub eax,ecx
- mov ecx,eax
- loop03:
- movd eax,mm4
- cmp eax,ebx
- je exit2
- movd mm1, dword ptr [esi]
- paddq mm1,mm4
- movq mm2,mm1 // mm2,总和
- pmuludq mm1,mm5
- psrlq mm1,58
- movq mm4,mm1// mm4 进位
-
- pmuludq mm1,mm7
- psubq mm2,mm1
-
- movd dword ptr[ebp],mm2
- lea esi, dword ptr [esi+4]
- lea ebp, dword ptr [ebp+4]
- dec ecx
- jnz loop03//////
- exit2:
- cmp ecx,ebx
- je exit1
-
- loop04:
- mov eax,dword ptr [esi]
- mov dword ptr[ebp],eax
-
- lea esi, dword ptr [esi+4]
- lea ebp, dword ptr [ebp+4]
- dec ecx
- jnz loop04/////
-
- jmp exit1
- ///-----------------以上是第一个加数大于第二个加数的求和-------------//
- fffdd:
- sub ecx, eax
- loop05:
- movd eax,mm4
- cmp eax,ebx
- je exit3
- movd mm1,dword ptr [edi]
- paddq mm1,mm4
-
- movq mm2,mm1 //mm2,总和
- pmuludq mm1,mm5
- psrlq mm1,58
- movq mm4,mm1 // mm4 进位
- pmuludq mm1,mm7
- psubq mm2,mm1
-
-
- movd dword ptr[ebp],mm2
- lea edi, dword ptr [edi+4]
- lea ebp, dword ptr [ebp+4]
- dec ecx
- jnz loop05//////
- exit3:
- cmp ecx,ebx
- je exit1
-
- loop06:
- mov eax,dword ptr [edi]
- mov dword ptr[ebp],eax
-
- lea edi, dword ptr [edi+4]
- lea ebp, dword ptr [ebp+4]
- dec ecx
- jnz loop06/////
- //--------------------------------------------//
- exit1:
-
- movd dword ptr [ebp],mm4
-
- pop ebp
- pop ebx
- pop edi
- pop esi
-
- emms
- ret
- }
- }/////*///
复制代码
作为对照,我写了一个c语言的大整数加法函数
- /*
- * 这是c语言写的大整数加法,作为对照。
- *
- * 为了简单一点:
- *
- * 1)要求第一个加数src1的实际长度大于等于第二个加数src2的实际长度。
- * 2)第二个加数的前面补零,与第一个加数的实际长度对齐。(实际处理中只需第二个加数src2的最大空间大于src1的实际长度即可)
- * 3)参数size1传递第一个加数的实际长度。
- */
- void big_add_c(unsigned long *dst,unsigned long *src1,unsigned long *src2,int size1)
- {
- int i,temp=0;
- for(i=0;i<size1;i++)
- {
- dst[i]=src1[i]+src2[i]+temp;
- temp=0;
- if(dst[i]>=BASE)
- {
- dst[i]-=BASE;
- temp=1;
- }
- }
- dst[i]=temp;
- }
复制代码 |
|