您的位置:首页 > 其它

汇编Q1:大数相乘

2017-11-16 23:17 204 查看
Q1、大数相乘。要求实现两个十进制大整数的相乘,输出乘法运算的结果。

.386
.model flat, stdcall
option casemap : none

includelib msvcrt.lib
include msvcrt.inc

endl equ <0DH,0AH>
.data
;numcharA/B最多容纳100个字节的字符,全部初始化为0
numCharA byte 100 dup(0)
numCharB byte 100 dup(0)
resultChar byte 200 dup(0)
numIntA dword 100 dup(0)
numIntB dword 100 dup(0)
result dword 200 dup(0)
;输入的格式
inputMsg byte "please input a large multiplier: ",0
szFmt_s byte "%s", 0
szFmt_d byte "%d", 0
;输出的格式
outputMsg byte "the result is %s",endl,0
outputMsg2 byte "the result is %s%s",endl,0
;把lenthA/B/C初始化为0
lengthA dword 0
lengthB dword 0
lengthC dword 0
;符号标志位,初始值为0,表示为正,为1表示为负
radix dword 10
negativeFlag byte 0
negativeImg byte "-"

.code
;=================================================================================
;字符串中的内容依次入栈,然后出栈,实现反转功能,并将byte型数组转化为dword型数组
;反转前为numChar,为byte型数组,每个byte存储字符'0'~'9',反转后为numInt,为dword型数组,每个dword存储数字0~9
;SS:ESP指示处于栈中的位置
str2int_reverse proc far C numChar:ptr byte, numInt:ptr dword, len:dword
mov ecx, len ;字符串长度即为循环的次数
mov esi, numChar
L1:
movzx eax, byte ptr [esi] ;高位0扩展
sub eax, 30H ;30H对应'0',字符'0'~'9' - '0'得到数字0~9
push eax ;eax入栈
inc esi ;esi++
loop L1 ;把byte数组numChar全部入栈,最高位先入栈,最低位最后入栈

mov ecx, len
mov esi, numInt
L2:
pop eax
mov dword ptr [esi], eax
add esi, 4
loop L2 ;把byte数组numChar依次出栈存到dword数组中,最低位先出栈,最高位最后出栈

ret
str2int_reverse endp

;===============================================================
;字符串中的内容依次入栈,然后出栈,实现反转功能,并将dword型数组转化为byte型数组
;反转前为numInt,为dword型数组,每个dword存储数字0~9,反转后为numChar,为byte型数组,每个byte存储字符'0'~'9'
;SS:ESP指示处于栈中的位置
int2str_reverse proc far C uses eax esi ecx
mov ecx, lengthC ;结果的长度为循环的次数
mov esi, 0
L1:
mov eax, dword ptr result[4 * esi]
add eax, 30H ;数字0~9 + '0'得到字符'0'~'9'
push eax
inc esi
loop L1 ;把dword数组numInt全部入栈,最高位先入栈,最低位最后入栈

mov ecx, lengthC
mov esi, 0
L2:
pop eax
mov byte ptr resultChar[esi], al ;依次出栈,把低八位存在resultChar的对应位置中,最低位先出栈,存在resultChar的最低位中
inc esi
loop L2

ret
int2str_reverse endp

;=======================================================================================================
;将数组A的长度赋给lengthA,并调用str2int_reverse
getStringALen proc far C uses eax
.if numCharA == 2DH ;2DH对应ASCII码为'-'
xor negativeFlag, 1
invoke crt_strlen, addr (numCharA + 1) ;跳过负号求字符串长度,结果在eax中
mov lengthA, eax
invoke str2int_reverse, addr (numCharA + 1), addr numIntA, lengthA ;字符串反转,且byte数组转dword数组
.else ;如果A为正数
invoke crt_strlen, addr numCharA ;求字符串长度,结果放在eax中
mov lengthA, eax
invoke str2int_reverse, addr numCharA, addr numIntA, lengthA
.endif
ret
getStringALen endp

;将数组B的长度赋给lengthB,并调用str2int_reverse
getStringBLen proc far C uses eax
.if numCharB == 2DH ;2DH对应ASCII码为'-'
xor negativeFlag, 1
invoke crt_strlen, addr (numCharB + 1) ;跳过负号求字符串长度,结果在eax中
mov lengthB, eax
invoke str2int_reverse, addr (numCharB + 1), addr numIntB, lengthB ;字符串反转,且byte数组转dword数组
.else ;如果A为正数
invoke crt_strlen, addr numCharB ;求字符串长度,结果放在eax中
mov lengthB, eax
invoke str2int_reverse, addr numCharB, addr numIntB, lengthB
.endif
ret
getStringBLen endp
;=============================================================================================================
;模拟手算的大数相乘算法
high_multiply proc far C uses eax ecx esi ebx
mov ebx, -1
OuterLoop:
inc ebx
cmp ebx, lengthA
jnb endLoop1 ;如果ebx >= lengthA,结束循环
xor ecx, ecx
InnerLoop:
xor edx, edx
mov eax, dword ptr numIntA[4 * ebx]
mul numIntB[4 * ecx] ;numIntA[4 * ebx] * numIntB[4 * ecx]结果放在EDX:EAX中,最大9*9 = 81也不会超过8个字节,所以结果只在EAX中
mov esi, ecx
add esi, ebx ;esi = ecx + ebx,即两个下标之和
add result[4 * esi], eax ;把两个位相乘的结果加到result的相应位上
inc ecx
cmp ecx, lengthB
jnb OuterLoop ;无符号数ecx>=lengthB时,下标超过lengthB - 1时跳出内层循环重新进行外层循环
jmp InnerLoop   ;不超过则继续进行内层循环
endLoop1:
mov ecx, lengthA
add ecx, lengthB
inc ecx ;ecx = lengthA + lengthB + 1
mov esi, offset lengthC
mov [esi], ecx ;将ecx赋给lengthC

xor ebx, ebx
CarryCul:
cmp ebx, ecx
jnb endLoop2 ;ebx >= ecx跳到endLoop2,跳出求进位的循环
mov eax, result[4  * ebx]
xor edx, edx
div radix
add result[4 * ebx + 4], eax ;result[i+1] += result[i]/10
mov result[4 * ebx], edx ;result[i] = result[i] % 10
inc ebx
jmp CarryCul
endLoop2:
mov ecx, lengthC ;让MoveZero从最后一位开始检查
MoveZero:
cmp dword ptr result[4 * ecx], 0
jnz endwhile1 ;result的末位不为0
dec ecx ;每检测到一个0,实际长度减一
jmp MoveZero
endwhile1:
inc ecx ;实际长度为最大下标加一
mov esi, offset lengthC
mov [esi], ecx ;将ecx赋给lengthC
invoke int2str_reverse ;将dword数组逆序并转化为byte数组

ret
high_multiply endp

;======================================================================================
;主函数
main proc
;键盘分别输入A和B,并存储为byte数组
invoke crt_printf, addr inputMsg
invoke crt_scanf, addr szFmt_s, addr numCharA
invoke crt_printf, addr inputMsg
invoke crt_scanf, addr szFmt_s, addr numCharB

invoke getStringALen ;将数组A的长度赋给lengthA,并调用str2int_reverse
invoke getStringBLen ;将数组B的长度赋给lengthB,并调用str2int_reverse

invoke high_multiply ;调用大数乘法子函数

.if negativeFlag == 1
invoke crt_printf, addr outputMsg2,addr negativeImg, addr resultChar
.else
invoke crt_printf, addr outputMsg, addr resultChar
.endif

ret
main endp
end main
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: