在 8086 上将两个 32 位数字相乘得到一个 64 位数字(32x32 => 64 位与 16 位相乘) [英] multiply two 32-bit numbers to get a 64-bit number, on a 8086 (32x32 => 64-bit with 16-bit multiplies)

查看:84
本文介绍了在 8086 上将两个 32 位数字相乘得到一个 64 位数字(32x32 => 64 位与 16 位相乘)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何在汇编中将两个 32 位数字相乘或一个 32 位与另一个 16 位相乘,有人知道算法吗?

How can i Multiply two 32bit digits in assembly or one 32bit another 16bit, anyone knows the algorithm ?

data1 dw 32bit
data2 dw 32bit    
mov ax,data2
Mul data1

推荐答案

首先,dw 用于创建 16 位(字")值.它不会保存 32 位值.您需要使用 dd 来存储 32 位dword",或使用一对 16 位值.

First, dw is used to create a 16-bit ("word") value. It won't hold a 32-bit value. You'd need to use dd to store a 32-bit "dword", or use a pair of 16-bit values.

将一对 32 位值相乘,结果可以是 64 位(例如 0xFFFFFFFF * 0xFFFFFFFF = 0xFFFFFFFE00000001).对于 8086(不仅仅是 80386 或更高版本的实模式代码),有一个 MUL 指令,但它仅限于乘以 2 个 16 位值(并获得 32 位结果).这意味着您需要将每个 32 位值视为一对 16 位值.

To multiply a pair of 32-bit values the result can be 64-bit (e.g. 0xFFFFFFFF * 0xFFFFFFFF = 0xFFFFFFFE00000001). For 8086 (and not just real mode code for 80386 or later) there is a MUL instruction, but it is limited to multiplying 2 16-bit values (and getting a 32-bit result). This means that you'd want to treat each 32-bit value as a pair of 16-bit values.

如果A被拆分为A_low(第一个32位数字的最低16位)和A_high(第一个32位数字的最高16位),并且B被拆分为B_low和B_high同样的方法;然后:

If A is split into A_low (the lowest 16-bits of the first 32-bit number) and A_high (the highest 16-bits of the first 32-bit number), and B is split into B_low and B_high in the same way; then:

  A * B = A_low * B_low
          + ( A_high * B_low ) << 16
          + ( A_low * B_high ) << 16
          + ( A_high * B_high ) << 32

代码可能如下所示(NASM 语法):

The code might look like this (NASM syntax):

         section .data
first:   dw 0x5678, 0x1234  ;0x12345678
second:  dw 0xDEF0, 0x9ABC  ;0x9ABCDEF0
result:  dw 0, 0, 0, 0      ;0x0000000000000000
         section .text

    mov ax,[first]          ;ax = A_low
    mul word [second]       ;dx:ax = A_low * B_low
    mov [result],ax
    mov [result+2],dx       ;Result = A_low * B_low

    mov ax,[first+2]        ;ax = A_high
    mul word [second]       ;dx:ax = A_high * B_low
    add [result+2],ax
    adc [result+4],dx       ;Result = A_low * B_low
                                     ; + (A_high * B_low) << 16

    mov ax,[first]          ;ax = A_low
    mul word [second+2]     ;dx:ax = A_low * B_high
    add [result+2],ax
    adc [result+4],dx       ;Result = A_low * B_low
                                     ; + (A_high * B_low) << 16
                                     ; + (A_low * B_high) << 16
    adc word [result+6], 0   ; carry could propagate into the top chunk

    mov ax,[first+2]        ;ax = A_high
    mul word [second+2]     ;dx:ax = A_high * B_high
    add [result+4],ax
    adc [result+6],dx       ;Result = A_low * B_low
                                     ; + (A_high * B_low) << 16
                                     ; + (A_low * B_high) << 16
                                     ; + (A_high * B_high) << 32

我们不需要在第二步之后需要adc word [result+6], 0 ([first+2] * [second]code>) 因为它的上半部分最多是 0xfffe.[result+4] 那时已经为零(因为这段代码只工作一次),所以 adc [result+4],dx 不能包装和产生一个执行.它最多可以产生0xffff.

We don't need adc word [result+6], 0 after the second step ([first+2] * [second]) because its high half is at most 0xfffe. [result+4] is already zero at that point (because this code only works once), so the adc [result+4],dx can't wrap and produce a carry out. It can at most produce 0xffff.

(可以用 adc dx, 0/mov [result+4], dx 来避免依赖于 result 的那部分> 已经归零.类似地,adc 进入归零寄存器可用于第一次写入 [result+6],以使此代码无需先归零即可使用 结果.)

(It could be done as adc dx, 0 / mov [result+4], dx to avoid depending on that part of result being already zeroed. Similarly, adc into a zeroed register could be used for the first write to [result+6], to make this code usable without first zeroing result.)

如果您实际上使用的是 80386 或更高版本,那么它会简单得多:

If you are actually using an 80386 or later, then it's much much simpler:

         section .data
first:   dd 0x12345678
second:  dd 0x9ABCDEF0
result:  dd 0, 0            ;0x0000000000000000
         section .text

    mov eax,[first]          ;eax = A
    mul dword [second]       ;edx:eax = A * B
    mov [result],eax
    mov [result+4],edx       ;Result = A_low * B_low

这篇关于在 8086 上将两个 32 位数字相乘得到一个 64 位数字(32x32 => 64 位与 16 位相乘)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆