- FasmWorld - https://fasmworld.ru -

32-битное умножение

Эта статья посвящена разбору примера умножения 32-битных чисел на 16-битном процессоре. Как вы наверно знаете, команда MUL [1] в 16-битном режиме позволяет умножать максимум 16-битные значения, поэтому для умножения 32-битных чисел необходим специальный алгоритм.

Умножать большие числа приходится по частям, а затем складывать эти промежуточные результаты. Чтобы всё стало понятно я напишу небольшую формулу. Допустим, нам надо умножить два 32-битных числа a и b. В результате должно получиться 64-битное число c. Обозначим как a1 — младшее слово a, a2 — старшее слово a, b1 — младшее слово b, b2 — старшее слово b. Тогда получается:

a = (a2<<16) + a1

b = (b2<<16) + b1

Символы <<16 обозначают сдвиг влево на 16 бит. По сути это то же самое, что умножить на 65536.

c = a x b = ((a2<<16) + a1) x ((b2<<16) + b2) =
= (a1 x b1) + ((a2 x b1)<<16) + ((a1 x b2)<<16) + ((a2 x b2)<<32)

Алгоритм очень напоминает способ умножения в столбик. Графически можно изобразить следующим образом:

Таким образом, в программе будет 4 этапа умножения и 3 сложения промежуточных результатов (обязательно с учётом переноса). У меня получился такой код:

use16                   ;Генерировать 16-битный код
org 100h                ;Программа начинается с адреса 100h

;Полный результат умножения будет находиться в регистрах BX:CX:SI:DI

    mov ax,word[a]      ;AX = младшее слово a
    mul word[b]         ;Умножение на младшее слово b
    mov di,ax           ;DI = младшая часть результата
    mov si,dx           ;SI = старшая часть результата
    sub cx,cx           ;CX = 0
    sub bx,bx           ;BX = 0

    mov ax,word[a+2]    ;AX = старшее слово a
    mul word[b]         ;Умножение на младшее слово b
    add si,ax           ;\ Прибавление промежуточного результата
    adc cx,dx           ;/ с учётом переноса

    mov ax,word[a]      ;AX = младшее слово a
    mul word[b+2]       ;Умножение на старшее слово b
    add si,ax           ;\
    adc cx,dx           ; > Прибавление промежуточного результата
    adc bx,bx           ;/  с учётом переноса

    mov ax,word[a+2]    ;AX = старшее слово a
    mul word[b+2]       ;Умножение на старшее слово b
    add cx,ax           ;\ Прибавление промежуточного результата
    adc bx,dx           ;/ с учётом переноса

    mov word[c],di      ;\
    mov word[c+2],si    ; \
    mov word[c+4],cx    ; / Сохранение результата в переменной c
    mov word[c+6],bx    ;/

    mov ax,4C00h        ;\
    int 21h             ;/ Завершение программы
;---------------------------------------------------------------------
align 4
a   dd $FFFFFFFF
b   dd $FFFFFFFF
c   dq ?

Подобным образом можно выполнять умножение чисел любой разрядности, причём необязательно одинаковой. Например, 64 x 64 бит, 32 x 64 бит, 16 x 32 бит и т.д.

Как вывести результат на экран читайте здесь [2].