汇编语言实验——大数相乘

1.1实验内容

实现两个十进制大整数的相乘(100位以上),输出乘法运算的结果。

1.2实验环境

Microsoft Visual Studio 2017+masm 32

1.3实验思路

1.3.1数据读入

大数相乘由于输入的数字过大而不能用一个dword来存储,所以需要使用数组来存取每一位,每一位大小范围在0-9中,按位读取输入,所以首先需要按照字符读取输入,将读入的两个数存储为两个字符数组中。

   ;键盘分别输入A和B,并存储为byte数组
    invoke printf, offset inputMsg
    invoke scanf,addr input,addr numCharA
    invoke printf,offset inputMsg
    invoke scanf,addr input,addr numCharB

1.3.2 将字符转为数字并反转存储

由于读入数据的是字符,所以需要先将字符转为数字,才能进行乘法,其次在大数相乘中,我们模拟手算乘法的过程,即乘数之间从低位向高位相乘并按位存储,再进行进位处理。所以,在转换为数字的过程中,我们通过将字符处理为数字后压栈,再依次退栈存储到数字数组中,实现将数字反转,这样再模拟乘法过程中可以从数组开始循环至数组结束。

 invoke strlen,numChar
        mov len,eax
        mov ecx,len
        L3:
            ;eax=esi[i]
            movzx eax,byte ptr[esi]
            ;减去'0',得到数字0-9
            sub eax,30H
            ;压栈
            push eax
            ;esi=numChar[i+1]
            inc esi
            loop L3
        mov ecx,len
        mov esi,numInt
        L4:
            ;从栈中弹出数据,依次存储到numInt中,达到反序的目的
            pop eax
            mov dword ptr[esi],eax
            ;esi+4,因为numInt为dword数组,4个偏移量为一个数据
            add esi,4
            loop L4
        ;再次调用strlen,使eax=len,返回时从eax即可读出len的值
        invoke strlen,numChar

1.3.3 模拟乘法

模拟乘法的过程为模拟手算乘法的过程,即x的第i位与y的第j位相乘时,结果存储到结果的第i+j位。

  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

1.3.4 进位

从低位到高位依次将结果的第i+1位加上第i位除10的结果,第i位等于第i位模10的结果。即result[i+1]+=result[i]/10,result[i]+=result[i]%10。

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从最后一位开始检查

1.3.5 清0

当i位数与j位数相乘时,最终结果不一定是i+j位,从最高位依次检测结果数组中的值是否为0,为0则长度减1。

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

1.3.6结果转为字符再输出

由于计算的结果也是反序存储在结果数组中,所以需要将结果数组反转并且转换位字符数组才能输出,所以采用和1.3.2类似的方法,将数字转为字符并压栈,循环结束后将字符依次退栈存储到结果中,最后输出字符串即可。

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

1.3.6 对负数进行处理

由于读入数据是一个一个字符的读入,所以如果读入的数字第一位为“-”,维护一个negativeFlag初始为0。若读入一个符号,则将其异或,则0变1,再有一个负号则1变0,当negativeFlag为1时,输出时则在结果之间输出负号。

;esi=numChar首地址
    mov esi,numChar
    ;eax=esi[0]
    movzx eax,byte ptr[esi]
    ;Symbol=eax,判断numChar第一个字符是否为负号
    mov Symbol,eax
    .if Symbol==2DH
        ;为负数,negativeFlag异或1
        xor negativeFlag,1
        ;调用strlen得到numChar的长度
        invoke strlen,numChar
        ;减去负号
        sub eax,1
        mov len,eax
        mov ecx,len
        ;esi=numChar[1]
        inc esi

1.4实验结果

  • 15
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值