-2

I have to read, store, and print two 32-bit numbers on the screen, then multiply them and print the result.

I have read the digits of the two numbers, and was able to print them, but if they are big enough, they overflow, not mentioning the fact, that, I have to multiply them, and I can't use 64-bit registers. I found the "multiple-precision arithmetic" stuff, but wasn't able to implement it. I know that I have to use the eax:edx registers, and I read about the carry bits too, still cannot grasp the essence of it. (MASM, 32-bit system)

The code I have so far:

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
rkhb
  • 14,159
  • 7
  • 32
  • 60
Tomi
  • 11
  • 2

1 Answers1

0

from grade school

(1^n) * (1^m) = 1^(n+m). So if you have two 32 bit numbers you need a 64 bit number as a result to handle all the cases. x86 supports putting the result in two registers, one gets the upper half the other gets the lower half. Read the x86 instruction set documentation.

So long as you allow twice as many bits for the result as the operands then the worst case numbers will fit, so you shouldnt need to worry about flags, just get the result.

For architectures that do not handle a result twice the width of the operands. Again, use elementary school math, and break the problem up into multiple steps. You can break your 32 bit numbers abcd * efgh into 16 bit numbers, and work the multiplication just like you do by hand. gh * cd, gh * ab, ef * cd, ef * ab. Then do the appropriate shifts and addition to combine those results in to the answer.

If I had the 16 bit hex numbers 0xabcd * 0x1234 the answer is ((0xabcd*4)<<0)+((0xabcd*3)<<4)+((0xabcd*2)<<8)+((0xabcd*1)<<12)

Which you could also do 4 bits at a time as above or 8 or 16 depending on what hardware you have, or could do it one bit at a time (which is where you realize that multiplication with binary is super simple, you either shift the number over and add or you dont). And this scales up as wide as you want, 1million bit number * 1million bit number = 2 million bit number. Just a matter of doing the smaller multiplies and shifts.

That is what we were doing in grade school, taking one digit at a time on the bottom multiplying it against the top and shifting it over some number of locations. You can implement this in software (most languages) using shifting and adding or if you have a hardware multiply can use that in some capacity.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Many architectures provide either a widening multiplication or an instruction to compute the upper half of the multiplication. – EOF May 02 '16 at 17:58
  • Alpha: `UMULH`. POWER: `mulh[w/d]`, ARM `[U/S]MULL`, MIPS: `MUL/MULT[U]/[D]MULH[U]`, x86(-64): `MUL/IMUL/MULX`. Basically *every* general purpose architecture I can find has such an instruction. – EOF May 02 '16 at 18:21