Умножение 64-битного числа на 32-битное число в 8086 асм

У меня были проблемы, даже инициируя решение проблемы. Я пытался учесть алгоритм умножения с повторным сложением, но какой бы алгоритм я ни рассматривал, мне кажется, что я зациклен на одной проблеме - максимальный размер регистра в 8086 - 16-битный.

data segment
num1 dw 0102h,0304h,0506h,0708h
num2 dw 0102h,0304h
res dw ?,?,?,?,?,?
data ends

code segment
assume CS:CODE, DS:DATA
start:
mov ax,DATA
mov DS,ax

.......... заполните код..........

На данный момент я застрял. Был бы признателен даже небольшой намек на код или просто алгоритм.

1 ответ

Для умножения 64-разрядного числа на 32-разрядное число с 16-разрядным процессором:

Шаг 1: предположим, что числа находятся в "базе 65536". Например, 64-разрядное число имеет 16 цифр в шестнадцатеричном виде (например, 0x0123456789ABCDEF) и будет иметь 4 цифры в "базе 65536" (например, {0123}{4567}{89AB}{CDEF}); и таким же образом 32-разрядное число будет иметь 2 цифры в "базе 65536".

Шаг 2: Чтобы умножить пару чисел, умножьте каждую цифру от первого числа на каждую цифру от второго числа, и добавьте это в правильное место в результате. Правильное место зависит от положения каждой цифры в исходных номерах. Например (в десятичном виде) для 90 * 30 вы должны сделать "9*3 = 27" и поместить его в "сотни" (например, 2700), потому что в первом числе справа была одна цифра плюс еще одна цифра для справа от второго числа, и это означает, что он должен идти туда, где в результате есть 2 цифры справа.

Пример:

    0x0123456789ABCDEF * 0x87654321
  = {0123}{4567}{89AB}{CDEF} * {8765}{4321}

                      {0123}{4567}{89AB}{CDEF}
    *                             {8765}{4321}
    ------------------------------------------
    =                             {3600}{18CF}  (from 4321 * CDEF)
    +                       {6CEA}{484B}{0000}  (from 8765 * CDEF)
    +                       {2419}{800B}{0000}  (from 4321 * 89AB)
    +                 {48CF}{7D77}{0000}{0000}  (from 8765 * 89AB)
    +                 {1232}{E747}{0000}{0000}  (from 4321 * 4567)
    +           {24B4}{B2A3}{0000}{0000}{0000}  (from 8765 * 4567)
    +           {004C}{4E83}{0000}{0000}{0000}  (from 4321 * 0123)
    +     {0099}{E7CF}{0000}{0000}{0000}{0000}  (from 8765 * 0123)
    ------------------------------------------
    =     {009A}{0CD0}{5C28}{F5C1}{FE56}{18CF}
    ------------------------------------------
    = 0x009A0CD05C28F5C1FE5618CF

Обратите внимание, что 8086 имеет команду "16 бит, умноженная на 16 бит = 32-битный результат" (MUL); и сложение может быть сделано 16 бит за один раз, используя один ADD инструкция сопровождается тем, сколько ADC инструкции вам нужны.

Также обратите внимание, что вы можете избежать некоторых дополнений путем слияния. Например:

                      {0123}{4567}{89AB}{CDEF}
    *                             {8765}{4321}
    ------------------------------------------
    =                             {3600}{18CF}  (from 4321 * CDEF)
    +                       {6CEA}{484B}{0000}  (from 8765 * CDEF)
    +                       {2419}{800B}{0000}  (from 4321 * 89AB)
    +                 {48CF}{7D77}{0000}{0000}  (from 8765 * 89AB)
    +                 {1232}{E747}{0000}{0000}  (from 4321 * 4567)
    +           {24B4}{B2A3}{0000}{0000}{0000}  (from 8765 * 4567)
    +           {004C}{4E83}{0000}{0000}{0000}  (from 4321 * 0123)
    +     {0099}{E7CF}{0000}{0000}{0000}{0000}  (from 8765 * 0123)
    ------------------------------------------
    =                             {3600}{18CF}  (from 4321 * CDEF)
    +                 {48CF}{7D77}{0000}{0000}  (from 8765 * 89AB)
    +     {0099}{E7CF}{0000}{0000}{0000}{0000}  (from 8765 * 0123)
    +                       {6CEA}{484B}{0000}  (from 8765 * CDEF)
    +           {24B4}{B2A3}{0000}{0000}{0000}  (from 8765 * 4567)
    +                       {2419}{800B}{0000}  (from 4321 * 89AB)
    +           {004C}{4E83}{0000}{0000}{0000}  (from 4321 * 0123)
    +                 {1232}{E747}{0000}{0000}  (from 4321 * 4567)
    ------------------------------------------
    =     {0099}{E7CF}{48CF}{7D77}{3600}{18CF}  (THESE WERE MERGED WITHOUT ADDITION)
    +           {24B4}{B2A3}{6CEA}{484B}{0000}  (THESE WERE MERGED WITHOUT ADDITION)
    +           {004C}{4E83}{2419}{800B}{0000}  (THESE WERE MERGED WITHOUT ADDITION)
    +                 {1232}{E747}{0000}{0000}  (from 4321 * 4567)
    ------------------------------------------
    =     {009A}{0CD0}{5C28}{F5C1}{FE56}{18CF}
    ------------------------------------------
    = 0x009A0CD05C28F5C1FE5618CF

Конечно, потому что не имеет значения, в каком порядке вы умножаете пары ("базовые 65536") цифр; Вы можете сделать все умножения в оптимальном порядке для слияния.

Для окончательного кода (с объединением); вы бы в конечном итоге с 8 MUL инструкции, 3 ADD инструкции и около 7 ADC инструкции. Мне лень писать код.;)

Другие вопросы по тегам