Умножение двух десятизначных 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 миллиона битное число. Просто делайте меньшие умножения и сдвиги.
Это то, что мы делали в начальной школе, беря по одной цифре внизу, умножая ее на вершину и сдвигая ее на некоторое количество мест. Вы можете реализовать это в программном обеспечении (большинство языков), используя сдвиг и добавление, или, если у вас есть аппаратное умножение, можете использовать это в некотором качестве.