【问题标题】:multiplying two long words on 68000 assembler在 68000 汇编器上将两个长字相乘
【发布时间】:2016-01-02 18:33:44
【问题描述】:

谁能帮我在 68000 汇编器上做这个练习? 创建一个程序,将两个无符号长字 v1 和 v3 相乘。产品是 64 位数字。 v1 qnd v2 的值分别在数据寄存器 D1 和 D2 上? 谢谢你的回答,对不起我的英语不好

【问题讨论】:

  • 你能展示你目前拥有的代码吗?还是我们您要求本网站上的某个人为您完成工作?
  • 不,我只是不知道如何在 64 位上制作结果

标签: 68000


【解决方案1】:

只要将无符号的 32 位量相乘,就可以使用以下方式: 理论:如果您的 32 位数量是 A 和 B,请像这样拆分它们: A=Ah*0x10000+Al,B=Bh*0x10000+Bl,其中Ah,Al,Bh,Bl的取值范围为0到0xFFFF。

那么,很明显,

A * B = Ah * Bh

这4个乘法中的每一个都是16bit*16bit->32bit,因此非常适合68000 mulu.w命令。

所以代码:

    ;unsigned d0.l * d1.l -> d2.l:d3.l (d2.l holds high part)

    move.w  d0,d3
    mulu.w  d1,d3 ;d3.l is Al*Bl now

    swap    d0
    swap    d1
    move.w  d0,d2
    mulu.w  d1,d2 ;d2.l is Ah*Bh now

    swap    d0
    move.w  d0,d4
    mulu.w  d1,d4 ;d4 is Al*Bh

    swap    d4
    moveq   #0,d5
    move.w  d4,d5
    clr.w   d4      ; d5:d4 is 0x0000:Nh:Nl:0x0000, where N is Al*Bh

    add.l   d4,d3
    addx.l  d5,d2   ;add Al*Bh*0x10000 to the partial result in d2:d3

    swap    d0
    swap    d1

    move.w  d0,d4
    mulu.w  d1,d4 ;d4 is Ah*Bl

    swap    d4
    moveq   #0,d5
    move.w  d4,d5
    clr.w   d4      ; d5:d4 is 0x0000:Nh:Nl:0x0000, where N is Ah*Bl

    add.l   d4,d3
    addx.l  d5,d2   ;add Ah*Bl*0x10000 to the partial result

    ;d2:d3 is now the result

当然,这段代码有很多优化的可能。

【讨论】:

    【解决方案2】:

    你的问题是 MUL 只有 16 位,这意味着如果你有一个 64 位的结果,你需要按 4 个 16 位的乘法和加法的顺序来做。然后将结果返回到两个寄存器中,因为每个寄存器都是 32 位的。

    假设你想要 A x B,A 是 AH 和 AL,B 是 BH 和 BL 你会得到一系列的部分产品:

    1: BL x AL
    2: BL x AH x 2^16
    3: BH x 2^16 x AL
    4: BH x 2^16 x AH x 2^16
    

    4 个部分积中的每一个都在 64 位字的自己的部分中累积,为了使事情更有趣,您需要考虑进位。

    就寄存器而言,我将介绍的内容与您需要的内容有所不同,但是如果您能理解它,您可以根据自己的练习进行更改。假设 A6 是堆栈,我们将在 D0 中返回高 32 位字的结果,并在 D1 中返回低 32 位字。这是我库中的一段代码

    umul32: link        a6, #0
            movem.l     d2-d4, -(sp)
            move.l      (multiB,a6), d4 ;B into d4
            move.l      (multiA,a6), d3 ;A into d3
            moveq       #0,d2
            moveq       #0,d1
            moveq       #0,d0
    mshift1:    lsr.l       #1,d4           ; look for 1 in multiplier
            bcc.s       mshift2     ; branch on 0
            add.l       d3,d1           ; add shifted A to product
            addx.l      d2,d0           ; add carry if found
    mshift2:    lsl.l       #1,d3           ; shift for next iteration
            roxl.l      #1,d2
            tst.l       d4          ; check for 1s
            bne.s       mshift1
            movem.l     (sp)+,d2-d4
            ulnk        a6
            move.l      (sp),(8,sp)     ;clean the 8 entries off the stack
            addq.l      8, sp
            rts
    

    【讨论】:

      【解决方案3】:

      这是由 Amiga Aztec C 编译器生成的用于将两个 32 位整数相乘的代码:

      D0/D1 : 输入 D0 : 输出

      move.w  d1,d2
      mulu    d0,d2
      move.l  d1,d3
      swap    d3
      mulu    d0,d3
      swap    d3
      clr.w   d3
      add.l   d3,d2
      swap    d0
      mulu    d1,d0
      swap    d0
      clr.w   d0
      add.l   d2,d0
      rts
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多