News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Long multiplication gone wrong

Started by Ravi Kiran, April 30, 2021, 10:24:15 PM

Previous topic - Next topic

Ravi Kiran

Any plz help me write a code for multiplying two long integers and
Displaying the result in console. I have written the following code which gives me strange results

          include \masm32\include\masm32rt.inc

          .data
           
                  var1 dd 56789342
                  var2 dd 67843286
                                                    ; The long integers to be multiplied

        .code

        start:

                 print " The product of var1 and var2 is: "
                 mov eax, var1
                 mul var2
                 print str$(edx)
                 print str$(eax)
                 inkey
                 invoke ExitProcess,0
   
    end start

 


   
   I don't understand where my code went horribly wrong . May be
   Writing the result to console is where I've gone wrong. Plz help me
   in this regard.
   

jj2007

There are two issues here:
1. After a print str$(edx), you should not expect that eax is still intact
2. Even if you preserve eax, as shown below with push+pop, printing a QWORD is not that simple. It works with MasmBasic Str$(edx::eax), though. IIRC the CRT also has QWORD printing, but not with registers.

useMasmBasic=1 ; conditional assembly
if useMasmBasic
  include \masm32\MasmBasic\MasmBasic.inc
else
  include \masm32\include\masm32rt.inc
endif
          .data
                  var1 dd 56789342
                  var2 dd 67843286
                                                    ; The long integers to be multiplied
        .code
        start:
                 print " The expected value is 3852775571057812", 13, 10
                 print " The product of var1 and var2 is: "
                 mov eax, var1
                 mul var2
                 if useMasmBasic
                  Print Str$(edx::eax), " (ok)", CrLf$
                 else
               push eax
               print str$(edx)
               pop eax
               print str$(eax), " (wrong)", 13, 10
                 endif
                 inkey
                 invoke ExitProcess,0
   
    end start


P.S.: A simple Inkey Str$("The product of var1 and var2 is %i", var1*var2) works, too, but I suppose you want to learn how to do it without external libraries ;-)

P.P.S. - the CRT way:
.data?
result QWORD ?
.code
mov dword ptr result, eax
mov dword ptr result[4], edx
invoke crt_printf, chr$("The product of var1 and var2 is %llu", 13, 10), result

Ravi Kiran

Yes sir I want to do it without using external library functions. Can't we use interrupts just like in 16 bit DOS programming to display the
Result?. My knowledge regarding functions like crt_printf, chr$ , str$
Console functions is limited and there is no detailed documentation
regarding the use of these console functions in masm32 help. I need
Detailed documentation of these functions. Can anyone help

jj2007

Google
site:masm32.com dwtoa
site:masmforum.com dwtoa

See in particular qword to ascii conversion

HSE

 Ok I read pretty bad  :biggrin:

Again:

          include \masm32\include\masm32rt.inc

          .data
           
                  var1 dd 56789342
                  var2 dd 67843286
                                                    ; The long integers to be multiplied
                  result qword 0.0
        .code

        start:

                 print " The product of var1 and var2 is: "
                 xor edx, edx                 ; just in case
                 mov eax, var1
                 mul var2
                 mov dword ptr result, eax
                 mov dword ptr result[4], edx
                 print sqword$(result),13,10,13,10
                 inkey
                 invoke ExitProcess,0
   
    end start

 

Equations in Assembly: SmplMath

raymond

QuoteI want to do it without using external library functions

And I assume you also want to restrict yourself to 32-bit programming at this time.

The first thing you need to understand is that the result of a multiplication is distributed between the two registers EDX/EAX, all being in the binary format, the least significant bits being in EAX. Before converting such result to "ascii" if the EDX register exceeds 9, you must split those two registers into two other values compatible with the decimal system; those two values can then be converted separately and their results concatinated to give you the final value. One caveat is that the result must not exceed 10^18.

Here is an example of how you could proceed.

.data
      pow9        dd    1000000000
      string      db    19 dup(?)   ;allow space for up to 18 digits
      last0       db    0           ;terminating 0 of the answer string
     
.code

start:
      mov   eax,56789342
      mov   edx,67843286
      mul   edx
      div   pow9       ;split it in two 'decimal compatible' registers
      push  eax         ;save the most significant digits
      mov   eax,edx     ;start with converting the least significant ones

      lea   edi,last0   ;to store the converted result
                        ;starting with the smallest digit
      call  dtoa
      pop   eax         ;retrieve the most significant digits
      call  dtoa        ;continue with converting the most significant ones

; This procedure then returns with the EDI register pointing to
; the most significant digit of the ascii answer in memory
; For example, you could use       invoke MessageBox,0,edi,0,MB_OK      to display it in a Windows message box.

;###########

dtoa:            ;assumes number to convert is in EAX
      mov   ecx,10
dtoa1:
      xor   edx,edx
      test  eax,eax
      jnz   @F
      ret
@@:
      div   ecx
      add   dl,30h
      dec   edi
      mov   [edi],dl
      jmp   dtoa1
Whenever you assume something, you risk being wrong half the time.
https://masm32.com/masmcode/rayfil/index.html

InfiniteLoop

Use PCLMULQDQ to multiply 64-bit into a 128-bit integer.