Умножение двух десятизначных 32-разрядных чисел на 32-разрядную архитектуру

Я должен прочитать, сохранить и распечатать два 32-битных числа на экране, затем умножить их и распечатать результат.

Я прочитал цифры двух чисел и смог их напечатать, но если они достаточно большие, они переполняются, не говоря уже о том, что мне приходится их умножать, и я не могу использовать 64-битные регистры, Я нашел "арифметику с множественной точностью", но не смог ее реализовать. Я знаю, что должен использовать регистры eax:edx, и я читал о битах переноса, но все еще не могу понять суть этого. (MASM, 32-битная система)

Код у меня так далеко:

INCLUDE Irvine32.inc
.data

NUM1        BYTE ?
NUM2        BYTE ?
NUM3        BYTE ?
NUM4        BYTE ?
NUM5        BYTE ?
NUM6        BYTE ?
NUM7        BYTE ?
NUM8        BYTE ?
NUM9        BYTE ?
NUM10   BYTE ?

NUMA        BYTE ?
NUMB        BYTE ?
NUMC        BYTE ?
NUMD        BYTE ?
NUME        BYTE ?
NUMF        BYTE ?
NUMG        BYTE ?
NUMH        BYTE ?
NUMI        BYTE ?
NUMJ        BYTE ?

SZAM1   DWORD   0
SZAM2   DWORD   0
SZAMOL  DWORD   0



.code
main proc

elso:
    call ReadChar
     mov  NUM1,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM2,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM3,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM4,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM5,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM6,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM7,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM8,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM9,al
    call WriteChar
    cmp AL,13
    JE masodik
    call ReadChar
     mov  NUM10,al
    call WriteChar
    cmp AL,13
    JE masodik



masodik:
    Call Crlf
    call ReadChar
     mov  NUMA,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMB,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMC,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMD,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUME,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMF,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMG,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMH,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMI,al
    call WriteChar
    cmp AL,13
    JE konvertal
    call ReadChar
     mov  NUMJ,al
    call WriteChar
    cmp AL,13
    JE konvertal

konvertal:
    Call Crlf

    sub NUM1, '0'
    sub NUM2, '0'
    sub NUM3, '0'
    sub NUM4, '0'
    sub NUM5, '0'
    sub NUM6, '0'
    sub NUM7, '0'
    sub NUM8, '0'
    sub NUM9, '0'
    sub NUM10, '0'

    sub NUMA, '0'
    sub NUMB, '0'
    sub NUMC, '0'
    sub NUMD, '0'
    sub NUME, '0'
    sub NUMF, '0'
    sub NUMG, '0'
    sub NUMH, '0'
    sub NUMI, '0'
    sub NUMJ, '0'

szamkiiras1:
    mov al,NUM10
    movzx eax,al
    imul eax,1
    add SZAM1,eax

    mov al,NUM9
    movzx eax,al
    imul eax,10
    add SZAM1,eax

    mov al,NUM8
    movzx eax,al
    imul eax,100
    add SZAM1,eax

    mov al,NUM7
    movzx eax,al
    imul eax,1000
    add SZAM1,eax

    mov al,NUM6
    movzx eax,al
    imul eax,10000
    add SZAM1,eax

    mov al,NUM5
    movzx eax,al
    imul eax,100000
    add SZAM1,eax

    mov al,NUM4
    movzx eax,al
    imul eax,1000000
    add SZAM1,eax

    mov al,NUM3
    movzx eax,al
    imul eax,10000000
    add SZAM1,eax

    mov al,NUM2
    movzx eax,al
    imul eax,100000000
    add SZAM1,eax

    mov al,NUM1
    movzx eax,al
    imul eax,1000000000
    add SZAM1,eax

    mov eax,SZAM1
    call WriteInt

szamkiiras2:
    Call Crlf
    mov al,NUMJ
    movzx eax,al
    imul eax,1
    add SZAM2,eax

    mov al,NUMI
    movzx eax,al
    imul eax,10
    add SZAM2,eax

    mov al,NUMH
    movzx eax,al
    imul eax,100
    add SZAM2,eax

    mov al,NUMG
    movzx eax,al
    imul eax,1000
    add SZAM2,eax

    mov al,NUMF
    movzx eax,al
    imul eax,10000
    add SZAM2,eax

    mov al,NUME
    movzx eax,al
    imul eax,100000
    add SZAM2,eax

    mov al,NUMD
    movzx eax,al
    imul eax,1000000
    add SZAM2,eax

    mov al,NUMC
    movzx eax,al
    imul eax,10000000
    add SZAM2,eax

    mov al,NUMB
    movzx eax,al
    imul eax,100000000
    add SZAM2,eax

    mov al,NUMA
    movzx eax,al
    imul eax,1000000000
    add SZAM2,eax

    mov eax,SZAM2
    call WriteInt

szorzas:
    Call Crlf
    mov SZAM1,eax
    mov SZAM2,ebx
    imul eax,ebx
    call WriteInt

main endp

end main

1 ответ

Из начальной школы

(1^n) * (1^m) = 1^(n+m). Поэтому, если у вас есть два 32-битных числа, вам нужно 64-битное число, чтобы обработать все случаи. x86 поддерживает помещение результата в два регистра, один получает верхнюю половину, другой - нижнюю. Прочитайте документацию по набору команд x86.

До тех пор, пока вы допускаете в два раза больше битов для результата, чем для операндов, тогда подходят наихудшие числа, поэтому вам не нужно беспокоиться о флагах, просто получите результат.

Для архитектур, которые не обрабатывают результат, в два раза шире операндов. Опять же, используйте математику в начальной школе и разбейте задачу на несколько этапов. Вы можете разбить ваши 32-битные числа abcd * efgh на 16-битные числа и выполнить умножение так же, как вы делаете это вручную. gh * cd, gh * ab, ef * cd, ef * ab. Затем выполните соответствующие изменения и дополнения, чтобы объединить эти результаты с ответом.

Если бы у меня были 16-битные шестнадцатеричные числа 0xabcd * 0x1234, ответ был бы ((0xabcd*4)<<0)+((0xabcd*3)<<4)+((0xabcd*2)<<8)+((0xabcd*1)<<12)

Что вы также можете делать 4 бита за раз, как указано выше, или 8 или 16, в зависимости от того, какое у вас оборудование, или можете делать это по одному биту за раз (когда вы понимаете, что умножение на двоичное является очень простым, вы либо сдвигаете номер над и добавить или вы не). И это масштабируется настолько широко, насколько вы хотите, 1-битное число * 1-миллионное число бит = 2 миллиона битное число. Просто делайте меньшие умножения и сдвиги.

Это то, что мы делали в начальной школе, беря по одной цифре внизу, умножая ее на вершину и сдвигая ее на некоторое количество мест. Вы можете реализовать это в программном обеспечении (большинство языков), используя сдвиг и добавление, или, если у вас есть аппаратное умножение, можете использовать это в некотором качестве.

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