News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How many errors did I make?

Started by frktons, July 22, 2010, 11:20:30 PM

Previous topic - Next topic

frktons

I feel a little disappointed, trying do write a very simple
routine in MASM32 and getting a lot of errors during assembling.

Here is the code. How many errors did I make?


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Dividing a number by ten and display result and remainder
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

include \masm32\include\masm32rt.inc

.data

     dd    div_result 0
     dd    remain      0
     dd    ten            10
     dd    num          17345


.code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    xor     edx, edx
    mov   eax, num
    mov   ecx, ten
    idiv   ecx
    mov   div_result, eax
    mov   remain, edx
    mov   ecx, num

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; display results
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    print "Original number: ", str$(ecx), 13, 10, 13, 10
    print "Number after division by ten: ",str$(eax),13,10,13,10
    print "Remainder: ",str$(edx),13,10
    inkey "Press any key to close..."


    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

Mind is like a parachute. You know what to do in order to use it :-)

Magnum

For starters, your data should be in this format.

Name   size       Value

ex.

Number dw  1234
Have a great day,
                         Andy

frktons

Quote from: Magnum on July 22, 2010, 11:28:19 PM
For starters, your data should be in this format.

Name   size       Value

ex.

Number dw  1234

OK thanks, I changed in this way:

     div_result dw 0
     remain      dw 0
     ten            dw 10
     num          dw 17345


Still a lot of errors, maybe less than before.  :P
What else I made wrong?

Well according to masm I have to define the variables in this way:

     div_result dd 0
     remain      dd 0
     ten            dd 10
     num          dd 17345


And the errors are in the use of the macro print.
Mind is like a parachute. You know what to do in order to use it :-)

KeepingRealBusy

I don't believe idiv gives you a remainder, just the quotient, but I do not use idiv so I may be wrong.

frktons

Quote from: KeepingRealBusy on July 22, 2010, 11:38:49 PM
I don't believe idiv gives you a remainder, just the quotient, but I do not use idiv so I may be wrong.

The error is in the use of print macro the remain of the code
should be fine now.
Mind is like a parachute. You know what to do in order to use it :-)

KeepingRealBusy

I looked it up, idiv does return a remainder.

Dave.

frktons

Quote from: KeepingRealBusy on July 22, 2010, 11:44:06 PM
I looked it up, idiv does return a remainder.

Dave.

Yes Dave, That is correct. I have only to understand what I did
wrong with the print macro.
Mind is like a parachute. You know what to do in order to use it :-)

jj2007

print expects dwords, i.e. dd, not dw
in addition, you can't use literal text followed by str$. Split it as follows:

    print "Original number: "
    print str$(ecx), 13, 10, 13, 10
    print "Number after division by ten: "
    print str$(eax),13,10,13,10
    print "Remainder: "
    print str$(edx),13,10
    inkey "Press any key to close..."

frktons

Quote from: jj2007 on July 22, 2010, 11:46:24 PM
print expects dwords, i.e. dd, not dw
in addition, you can't use literal text followed by str$. Split it as follows:

    print "Original number: "
    print str$(ecx), 13, 10, 13, 10
    print "Number after division by ten: "
    print str$(eax),13,10,13,10
    print "Remainder: "
    print str$(edx),13,10
    inkey "Press any key to close..."


Great, finally it assembled! but the result is very poor:

Original number: -1040318464

Number after division by ten: 30

Remainder: 1170728
Press any key to close...


Something is still wrong.  ::)
Mind is like a parachute. You know what to do in order to use it :-)

frktons

OK I found the error, the correct version is:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Dividing a number by ten and display result and remainder
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

include \masm32\include\masm32rt.inc

.data

    div_result dd 0
    remain      dd 0
    ten            dd 10
    num          dd 17345


.code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    xor     edx, edx
    mov    eax, num
    mov    ecx, ten
    idiv    ecx
    mov   div_result, eax
    mov   remain, edx
    mov   ecx, num

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; display results
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


    print "Original number: "
    print sstr$(num), 13, 10, 13, 10
    print "Number after division by ten: "
    print sstr$(div_result),13,10,13,10
    print "Remainder: "
    print sstr$(remain),13,10,13,10
    inkey "Press any key to close..."


    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


Now let's move a step further, I'm still very confused about declaring and
calling procedures in MASM.
I know we can push the parameters to pass, and pop them, or we can pass
them directly in the calling.
But I am not able to do either of them.

Could someone please use this code and make a procedure with the
instructions to divide, and the call to it passing the parameters?

Thanks
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

you can combine the print and chr$ macros to handle literal strings
it is convenient, but you can't make multiple use of the string
        print   chr$('Hello',32,'World',13),10
i tried to show different ways to combine ASCII numerics, as well
the chr$() macro actually creates the null-terminated string and returns its' address for the print macro

here is one way to make the proc...
IDivide PROTO   :DWORD,:DWORD


IDivide PROC    dwDividend:DWORD,dwDivisor:DWORD

;Returns: EAX = Quotient
;         EDX = Remainder

        mov     eax,dwDividend
        xor     edx,edx
        idiv dword ptr dwDivisor
        ret

IDivide ENDP

dedndave

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Dividing a number by ten and display result and remainder
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

IDivide PROTO   :DWORD,:DWORD

        INCLUDE \masm32\include\masm32rt.inc

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Data Area
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

        .DATA

num        dd 17345

        .DATA?

div_result dd ?
remain     dd ?

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Code Area
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

        .CODE

_main   PROC

;divide "num" by 10

        INVOKE  IDivide,num,10
        mov     div_result,eax
        mov     remain,edx

; display results

        print   chr$('Dividend:  ')
        mov     eax,num
        print   str$(eax),13,10,13,10

        print   chr$('Quotient:  ')
        mov     eax,div_result
        print   str$(eax),13,10,13,10

        print   chr$('Remainder: ')
        mov     eax,remain
        print   str$(eax),13,10,13,10

;wait for a keypress and terminate

        inkey   "Press any key to close..."
        exit

_main   ENDP

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Signed Integer Division Routine
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

IDivide PROC    dwDividend:DWORD,dwDivisor:DWORD

;Returns: EAX = Quotient
;         EDX = Remainder

        mov     eax,dwDividend
        xor     edx,edx
        idiv dword ptr dwDivisor
        ret

IDivide ENDP

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
        END     _main
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

frktons

Thanks Dave, it looks pretty clear  :U

So when I declare the procedure prototype I only declare the generic
data type to be passed:

IDivide PROTO   :DWORD,:DWORD


Any reason it is before the include:

IDivide PROTO   :DWORD,:DWORD

INCLUDE \masm32\include\masm32rt.inc

or it is the same?

When I call the procedure I just use the names of the variables:

INVOKE  IDivide,num,10


And the procedure is defined with both data type and name of variables:

IDivide PROC    dwDividend:DWORD,dwDivisor:DWORD
......
IDivide ENDP


Till now it looks pretty much like the C way of doing the same thing,
except I don't know if you can declare a return value as well or you just
take care of the address, registers to pass.

Well, now a little doubt about the difference between call and invoke.

Are they the same or they use different syntax and are used in different ways
for different purposes?

And the final doubt: if I use the old way of pushing and popping the
data between the calls by myself, how would I do that in this specific case?  ::)

Thanks for your patience.

Edit: a problem during assemblying time:

Microsoft (R) Macro Assembler Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: C:\masm32\examples\dividebythe_dave.asm
C:\masm32\examples\dividebythe_dave.asm(5) : error A2119:language type must be s
pecified
C:\masm32\examples\dividebythe_dave.asm(62) : error A2112:PROC and prototype cal
ling conventions conflict
_
Assembly Error
. . .


Well I had to change the order of include and proc prototype
in order to have it compiling successfully:

INCLUDE \masm32\include\masm32rt.inc

IDivide PROTO   :DWORD,:DWORD


And now it works fine:

Dividend:  17345

Quotient:  1734

Remainder: 5

Press any key to close...




Mind is like a parachute. You know what to do in order to use it :-)

frktons

I discovered a thread from 2004 that deals with call and invoke
better if I have a look:

call vs invoke

:P

Mind is like a parachute. You know what to do in order to use it :-)

dedndave

yes - i should have caught that   :bg
but, i am pretty sure the PROTO must come before the INVOKE
PROTO is the difference between CALL and INVOKE (other than how the parms are pushed on the stack)
for INVOKE, the name must be pre-defined - not so for CALL

i used the constant 10, only because it is always the same value in this case
and, i wanted to demonstrate that a constant or a variable can be used as a parm