【问题标题】:assembly multiply two 16 bit program using 68hc11汇编使用 68hc11 将两个 16 位程序相乘
【发布时间】:2025-12-31 12:55:07
【问题描述】:

我需要编写一个程序来

  • 将存储在 {M, M+1} 和 {N, N+1} 的一对 16 位数字相乘,并将得到的 32 位乘积存储在 {P, P+1,P+2, P+ 3}。
  • 将存储在 {M, M+1} 和 {N, N+1} 的一对 16 位数字相乘,然后 将生成的 32 位乘积存储在 {P, P+1,P+2, P+3}。
  • 所有内容都以“MSB 最低地址”顺序存储,即 (P) 将 是乘积的最高字节,(P+3) 是最低的 字节。

  • 安排 M 生活在 200-201 美元,N 生活在 202-203 美元,P 生活在 210-213 美元。

  • 提示:因为 HC11 的 MUL 指令只有 8 位,所以使用 部分乘积法。

  • 用以下每种情况测试您的解决方案,并给出您的 生成的 32 位答案:

  • 案例 1:M=$4B18 和 N=$71C9

  • 案例 2:M= N=$8FED

好的,我找到了下面的示例代码,用于将两个 32 位数字相乘。

我需要将代码转换为 HC11 的程序集版本,然后更正它以乘以 16 位而不是 32 位数字...

我相信 68hc11 的 mov 应该改为 LD,然后呢?

.model small

.data
        mult1 dw 2521H
              dw 3206H
        mult2 dw 0A26H
              dw 6400H
        ans   dw 0,0,0,0

.code
        mov ax,@data
        mov ds,ax

;       LEA SI,ans

        mov ax,mult1
        mul mult2
        mov ans,ax
        mov ans+2,dx

        mov ax,mult1+2
        mul mult2
        add ans+2,ax
        adc ans+4,dx
        adc ans+6,0

        mov ax,mult1
        mul mult2+2
        add ans+2,ax
        adc ans+4,dx
        adc ans+6,0

        mov ax,mult1+2
        mul mult2+2
        add ans+4,ax
        adc ans+6,dx

        mov ax,4C00h
        int 21h
end

【问题讨论】:

  • 为什么要投反对票?我在问如何将汇编代码转换为 HC11 的代码。非常简单。
  • 我没有投票,但你只是从某个地方转储了一段代码,基本上说“在这里,为我翻译这个”。 x86 指令集参考手册is freely available,我相信 68HC11 也是如此。那么具体是什么原因你没有找到合适的 68HC11 指令(或指令组合)呢?

标签: assembly


【解决方案1】:

这是我在 2004 年写的。希望对您有所帮助:

************************************************************************************************
* This library is used to extend the HC11's math capabilities                                  *
************************************************************************************************ 

MULU_16_16: PSHD               ; The HC11 has an 8-bit CPU, and so cannot deal with 16-bit
           PSHD               ; multiplication. MULU_16_16 takes two 16-bit numbers and
           LDAA  $09,SP       ; multiplies them together, placing the 32-bit result in 
           LDAB  $07,SP       ; the stack space where the two operands once occupied.
           MUL                ; This routine doesn't need any static variables, but it
           STD   $02,SP       ; does use 10 bytes of stack space, including the call to
           LDAA  $09,SP       ; the sub, and all parameter passing. A call to this sub
           LDAB  $06,SP       ; would look like this:
           MUL                ; LDD   Operand1    ; I used D to illustrate, but this should
           ADDB  $02,SP       ; PSHD              ; also work using an index register, or a
           ADCA  #0           ; LDD   Operand2    ; MOVW instruction. Placing values on the
           STD   $01,SP       ; PSHD              ; stack before the call is passing factors.
           LDAA  $08,SP       ; JSR   MULU_16_16  ; Call the sub.
           LDAB  $07,SP       ; PULD              ; Most significant word of product.
           MUL                ; PULD              ; Least significant word of product.
           ADDB  $02,SP       
           ADCA  $01,SP       ; READ THIS DAMMIT! You MUST re-adjust the stack after calling 
           STD   $01,SP       ; MULU_16_16 even if you aren't interested in the result.
           LDAA  $08,SP       ; What's more, you MUST PLACE four bytes on the stack before
           LDAB  $06,SP       ; calling MULU_16_16. If you do not do either of these things,
           MUL                ; your program will get a nice surprise when you try to RTS
           ADDB  $01,SP       ; next. Remember, this function modifies values on the stack
           ADCA  #0           ; that were placed there BEFORE the return address from the JSR
           STD   $00,SP       ; that called it. 
           PULD               ; Destroy the stack space we created at the beginning of this 
           STD   $04,SP       ; sub.
           PULD
           STD   $04,SP
           RTS


MULU_32_32:LDD   $08,SP       ; Here we go... 32-bit by 32-bit multiply. Ready for loads of
           PSHD               ; technical detail? Here we take advantage of the routine we
           LDD   $06,SP       ; just wrote: MULU_16_16. We not only use the sub directly, but
           PSHD               ; also extend its algorithm. We need a 64-bit product (R), from
           JSR   MULU_16_16   ; two 32-bit factors (Q, P). We use the property:
           LDD   $0C,SP       ; R=(Pu*Qu*2^32)+(Pu*Ql*2^16)+(Pl*Qu*2^16)+(Pl*Ql)
           PSHD               ; to extend the reach of the HC11's puny 8-bit multiply. Also
           LDD   $08,SP       ; like the above routine, this one doesn't use any static 
           PSHD               ; memory space for operands or results. The calling procedure
           JSR   MULU_16_16   ; is similar:
           LDD   $0E,SP       ; LDD   Operand1(LSW) ; The stacking method is a little weird
           PSHD               ; PSHD                ; for people used to programming big-
           LDD   $0E,SP       ; LDD   Operand1(MSW) ; endian CPUs, the LSW of the operand is
           PSHD               ; PSHD                ; PSH'd before the MSW. It will be pulled
           JSR   MULU_16_16   ; LDD   Operand2(LSW) ; off in a logical order, however. Again,
           LDD   $00,SP       ; PSHD                ; D was used to illustrate, but the
           ADDD  $04,SP       ; LDD   Operand2(MSW) ; parameter passing could be done with
           STD   $04,SP       ; PSHD                ; MOVW's.
           LDD   $02,SP       ; JSR   MULU_32_32    ; Call the sub
           ADCB  $07,SP       ; PULD                ; Most significant word of product
           ADCA  $06,SP       ; PULD                ; Second most significant word of product
           STD   $06,SP       ; PULD                ; Third most significant word of product
           LDD   $08,SP       ; PULD                ; Least significant word of product
           ADCB  $07,SP       ; After multiplying (Pu*Qu), (Pu*Ql) and (Pl*Qu), we begin
           ADCA  $06,SP       ; adding values so we can reclaim a little stack space. Notice 
           STD   $08,SP       ; that we haven't been PUL'ing values. The stack just keeps
           LDD   $0A,SP       ; growing. Also note that MULU_32_32 is somewhat of a cycle
           ADCB  #0           ; and stack eater. On an HC11, each MUL opcode takes 10 cycles
           ADCA  #0           ; to execute, and there are 16 MUL's for each MULU_32_32 call.
           STD   $0A,SP       ; That's 160 cycles in MUL's alone. Furthurmore, the stack use
           LDD   $04,SP       ; hits a maximum of 28 bytes. Undesirable, but it might be the
           STD   $06,SP       ; only way for an HC11 to get a 64-bit result. HC12 users have
           PULD               ; the EMUL opcode which does 16-bit by 16-bit and takes only 3 
           PULD               ; cycles to complete.
           PULD               ; This sub also carries the same warning as the one above:
           LDD   $0C,SP       ; Watch your stack carefully! Before and after the call.
           PSHD               ; 
           LDD   $0A,SP       ; 
           PSHD               ; 
           JSR   MULU_16_16   ;
           LDD   $02,SP       ; 
           ADDD  $04,SP       ; 
           STD   $04,SP       ; 
           LDD   $06,SP       ; 
           ADCB  #0           ; 
           ADCA  #0           ; 
           STD   $06,SP       ; 
           LDD   $08,SP       ; 
           ADCB  #0           ; 
           ADCA  #0           ; 
           STD   $08,SP       ; 
           PULD               ; 
           STD   $00,SP       ; 
           PULD               ; 
           STD   $08,SP       ; 
           PULD               ; 
           STD   $08,SP       ; 
           PULD               ; 
           STD   $08,SP       ; 
           PULD               ; 
           STD   $08,SP       ; 
           RTS                ; 

【讨论】:

  • 这不是 68HC11 兼容的代码,因为没有 SP 索引模式。可能是 HC12?
  • 你是对的。 SP 是其他一些寄存器的占位符。 X 或 Y 在 HC11 的情况下。但我向你保证,这是使用摩托罗拉 As11 的有效代码。