加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

80x86汇编:多字节数相乘的编程方法

(2019-01-17 22:10:37)
标签:

it

分类: 80x86

用汇编语言编写程序,实现两个64位二进制数相乘。

CPU 的位数是有限的,而设计要求,却没有限制。
如果想用升级 CPU 来解决高精度运算的需求,恐怕,是没有指望了。
码农,也只能通过编写程序,来解决了。

80x86  CPU 只有 16 位乘 16 位的指令。
如果用 386 的 32 位指令,也只有 32 位乘以 32 位的指令。

一个64位数,可以分解成两个32位数,然后按照小学学过的方法、步骤,慢慢乘。
 80x86汇编:多字节数相乘的编程方法

数字再大,就多分解几个部分。然后,慢慢乘呗。
你只要有耐心,无论多少位,都可以求出结果。
不会编程?
那你就等着微电子技术发展,高位数的 CPU 问世吧。

做而论道编写了程序,可以实现两个 64 位二进制数相乘。
乘积将有 128 位数,共有 16 字节。
做而论道还写了显示程序,可以把乘积显示出来。

显示出来的积,对不对呢?
可以用 WinXP 中的计算器来进行检验。
检验结果,当然是证明做而论道的程序,是完全正确的了。

但是,WinXP 中的计算器只能算出 8 字节的结果。
所以,也就只能检验比较小的乘积了。
较大的乘积,就连 Windows 都算不出来,也就无法判别了。

当然,是不是可以用 C 语言写个程序,来对比一下结果?
这就由有兴趣、有能力的网友来做吧。

做而论道编写的程序如下:

ASSUME   CS:CODE, DS:DATA
DATA   SEGMENT

;DQ,定义八字节,共64位二进制数
;DD,定义四字节,共32位二进制数

    XL   DD   123456   ;32位二进制数
    XH   DD   654321   ;0~4294967295
    
    YL   DD   13579
    YH   DD   987654
    
    Z1   DD   0        ;积为128位
    Z2   DD   0
    Z3   DD   0
    Z4   DD   0
    
    NN   DW   16       ;积为16字节
    JV   DB   10       ;进制, 显示十进制数
    
DATA   ENDS

CODE   SEGMENT

START:
    MOV   AX, DATA
    MOV   DS, AX

    JMP   PRG_8086
;-----------------------------------------------
.386                   ;用32位乘32位的指令
    MOV   EAX, XL
    MUL   YL
    MOV   Z1, EAX
    MOV   Z2, EDX

    MOV   EAX, XH
    MUL   YL
    ADD   Z2, EAX
    ADC   Z3, EDX

    MOV   EAX, XL
    MUL   YH
    ADD   Z2, EAX
    ADC   Z3, EDX
    ADC   Z4, 0

    MOV   EAX, XH
    MUL   YH
    ADD   Z3, EAX
    ADC   Z4, EDX

    JMP   DS1          ;去显示乘积
;-----------------------------------------------
PRG_8086:              ;用16位乘16位的指令
.8086
    MOV   SI, 0
    MOV   CH, 4        ;乘数1有4个字
@1: MOV   CL, 4        ;乘数2有4个字
    MOV   BX, 0
@@: MOV   AX, WORD  PTR  XL[SI]
    MUL   WORD  PTR  YL[BX]
    ADD   WORD  PTR  Z1[SI + BX + 0], AX
    ADC   WORD  PTR  Z1[SI + BX + 2], DX
    ADD   BX, 2
    DEC   CL
    JNZ   @B
    ADD   SI, 2
    DEC   CH
    JNZ   @1           ;共循环16遍

;如果用 8 位乘 8 位的指令,就要循环64遍了
;-----------------------------------------------
DS1:                   ;显示乘积
.8086
    LEA   SI, Z1
    CALL  DISP_N_BYTE

EXIT:
    MOV   AH, 4CH
    INT   21H
;-----------------------------------------------
DISP_N_BYTE:
    MOV   BP, SI
    MOV   DX, 0
@@: CALL  DIV_N_BYTE
    MOV   AL, AH
    PUSH  AX
    INC   DX
    CALL  TEST_0
    CMP   AL, 0
    JNE   @B
    
    MOV   AH, 2
    MOV   CX, DX
@@: POP   DX
    OR    DL, '0'
    INT   21H
    LOOP  @B
    RET
;-----------------------------------
DIV_N_BYTE:
    MOV   AH, 0
    MOV   BX, NN
    DEC   BX    
    MOV   CX, NN
@@: MOV   AL, [SI + BX]
    DIV   JV         ;AHAL/JV=AL...AH
    MOV   [SI + BX], AL
    DEC   BX
    LOOP  @B
    RET         
;-----------------------------------
TEST_0:
    PUSH  SI
    MOV   AL, 0
    MOV   BX, 0
    MOV   CX, NN
    MOV   SI, BP
@@: OR    AL, [SI + BX]
    INC   BX
    LOOP  @B
    POP   SI
    RET
;-----------------------------------------------
CODE   ENDS
    END   START

说明:
做而论道,是本博主在百度开博时用的昵称。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有