News:

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

Code Trouble

Started by etow, January 24, 2008, 08:21:56 PM

Previous topic - Next topic

etow

.686 ; create 32 bit code

.Model flat, StdCall  ;32 bit memory model
Option CaseMap :none  ; case sensitive

Include   \masm32\include\windows.inc
Include   \masm32\macros\macros.asm       ; MASM support macros

  ; -----------------------------------------------------------------
  ; include files that have MASM format prototypes for function calls
  ; -----------------------------------------------------------------
Include   \masm32\include\masm32rt.inc

  ; ------------------------------------------------
  ; Library files that have definitions for function
  ; exports and tested reliable prebuilt code.
  ; ------------------------------------------------
IncludeLib   \masm32\lib\msvcrt.lib

.Code

start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   Call Main
   inkey        ; pause the screen while waiting for user to press any key
                ; to continue
    exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Main Proc Uses Ecx
   Local Number:DWord
   Local Remainder:DWord
   Local Quotient:DWord
   Local Factor:DWord
   Local PrimeFactor:DWord
   Local WantContinue:DWord
   ; Number is the integer to be factored out
   ; PrimeFactor is the string containing the factored primes of the user's integer
   ; WantContinue is the sentinel value of the first while loop
    ;-----------------------------------------------------------

    Mov WantContinue, 0
    Mov PrimeFactor, " "

    .While ((WantContinue >= 0) && (WantContinue < -1))
       print chr$(13, 10)
       Mov Number, sval(input("Enter an integer value for Number : "))
       Mov Factor, 2
       Mov Ecx, Number
       .If (Ecx >= 2)
         .While Factor <= Ecx  ; Factor <= (Number = Ecx)
             Mov Eax, Number
             Mov Ebx, Factor
             Cdq
             IDiv Ebx
             Mov Quotient, Eax   ; Quotient = Number / Factor

             Mov Eax, Number
             Cdq
             Mov Ebx, Factor
             IDiv Ebx
             Mov Remainder, Edx  ; Remainder = Number mod Factor

          .If (Remainder == 0)
             Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor))
             Mov Quotient, Ecx   ; Quotient = Number = Ecx
             Mov Eax, Number
               Mov Ebx, Factor
               Cdq
               IDiv Ebx
               Mov Quotient, Eax   ; Quotient = Number / Factor

               Mov Eax, Number
               Cdq
               Mov Ebx, Factor
               IDiv Ebx
               Mov Remainder, Edx  ; Remainder = Number mod Factor
          .ElseIf
              Inc Factor   ; Factor = Factor + 1
          .EndIf
        .EndW
         print str$(Ecx)
         print chr$(" = ")
         print str$(PrimeFactor)  ; output the prime factorization of the number
         print chr$(13, 10)
         Mov WantContinue, sval(input("Enter -1 to quit program : "))
         print chr$(13, 10)
       .ElseIf (Number == 1)
                print str$(Number)
                print chr$(" = ")
                print str$(Number)
                print chr$(13, 10)
                Mov WantContinue, sval(input("Enter -1 to quit program : "))
                print chr$(13, 10)
       .ElseIf (Number <= 0)
           print chr$(13, 10)
           print chr$("Invalid integer entered!")
           print chr$(13, 10, 13, 10)
           Mov WantContinue, sval(input("Enter -1 to quit program : "))
           print chr$(13, 10)
       .EndIf
    .EndW
    print chr$(13, 10)        ; a return key space will be outputted to the screen

  Ret
Main EndP

End start

---------------------------------------------------------------------------------------------------

The above code does not work.

For example,
Here is how the code should work,
If Number = 30,  The PrimeFactor will display -->  30 = 2 * 3 * 5  on the screen
If Number = 72,   The Prime Factor will display --> 72 = 2 * 2 * 2 * 3 * 3  on the screen
PrimeFactor is a string.

The instruction: Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor)) does not seem to work.  Did I write out this instruction wrong?

Please help me.

Thanks

jj2007

Which error message do you get? It would also help readers if you put the lines that don't work in bold...

etow

.686 ; create 32 bit code

.Model flat, StdCall  ;32 bit memory model
Option CaseMap :none  ; case sensitive

Include   \masm32\include\windows.inc
Include   \masm32\macros\macros.asm       ; MASM support macros

  ; -----------------------------------------------------------------
  ; include files that have MASM format prototypes for function calls
  ; -----------------------------------------------------------------
Include   \masm32\include\masm32rt.inc

  ; ------------------------------------------------
  ; Library files that have definitions for function
  ; exports and tested reliable prebuilt code.
  ; ------------------------------------------------
IncludeLib   \masm32\lib\msvcrt.lib

.Code

start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   Call Main
   inkey        ; pause the screen while waiting for user to press any key
                ; to continue
    exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Main Proc Uses Ecx
   Local Number:DWord
   Local Remainder:DWord
   Local Quotient:DWord
   Local Factor:DWord
   Local PrimeFactor:DWord
   Local WantContinue:DWord
   ; Number is the integer to be factored out
   ; PrimeFactor is the string containing the factored primes of the user's integer
   ; WantContinue is the sentinel value of the first while loop
    ;-----------------------------------------------------------

    Mov WantContinue, 0
    Mov PrimeFactor, " "

    .While ((WantContinue >= 0) && (WantContinue < -1))
       print chr$(13, 10)
       Mov Number, sval(input("Enter an integer value for Number : "))
       Mov Factor, 2
       Mov Ecx, Number
       .If (Ecx >= 2)
         .While Factor <= Ecx  ; Factor <= (Number = Ecx)
             Mov Eax, Number
             Mov Ebx, Factor
             Cdq
             IDiv Ebx
             Mov Quotient, Eax   ; Quotient = Number / Factor

             Mov Eax, Number
             Cdq
             Mov Ebx, Factor
             IDiv Ebx
             Mov Remainder, Edx  ; Remainder = Number mod Factor

          .If (Remainder == 0)
             Mov PrimeFactor, cat$(str$(PrimeFactor), chr$(" * "), str$(Factor))              Mov Quotient, Ecx   ; Quotient = Number = Ecx
             Mov Eax, Number
               Mov Ebx, Factor
               Cdq
               IDiv Ebx
               Mov Quotient, Eax   ; Quotient = Number / Factor

               Mov Eax, Number
               Cdq
               Mov Ebx, Factor
               IDiv Ebx
               Mov Remainder, Edx  ; Remainder = Number mod Factor
          .ElseIf
              Inc Factor   ; Factor = Factor + 1
          .EndIf
        .EndW
         print str$(Ecx)
         print chr$(" = ")
        print str$(PrimeFactor)  ; output the prime factorization of the number          print chr$(13, 10)
         Mov WantContinue, sval(input("Enter -1 to quit program : "))
         print chr$(13, 10)
       .ElseIf (Number == 1)
                print str$(Number)
                print chr$(" = ")
                print str$(Number)
                print chr$(13, 10)
                Mov WantContinue, sval(input("Enter -1 to quit program : "))
                print chr$(13, 10)
       .ElseIf (Number <= 0)
           print chr$(13, 10)
           print chr$("Invalid integer entered!")
           print chr$(13, 10, 13, 10)
           Mov WantContinue, sval(input("Enter -1 to quit program : "))
           print chr$(13, 10)
       .EndIf
    .EndW
    print chr$(13, 10)        ; a return key space will be outputted to the screen

  Ret
Main EndP

End start

---------------------------------------------------------------------------------------------------

The lines in red bold color is the ones I have trouble with.

etow

There are no error messages.
When I enter Number -1 and Numbers less than -1, the program gets stuck in an infinite loop.
Only Numbers 0 and 1 respond to the program.
Numbers 2 and greater gets the program stuck in an infinite loop too.

MichaelW

The high-level constructs (.IF, .WHILE, .REPEAT), PROTO, and INVOKE by default treat initializers as unsigned. To change this behavior, precede the initializer with SBYTE PTR, SWORD PTR, or SDWORD PTR.

mov eax, 1
.IF eax > -1
  ; This tests for eax > 0FFFFFFFFh
.ENDIF
mov eax, 1
.IF eax > SDWORD PTR -1
  ; This tests for eax > -1
.ENDIF

eschew obfuscation

jj2007

Quote from: MichaelW on January 25, 2008, 01:22:58 AM
The high-level constructs (.IF, .WHILE, .REPEAT), PROTO, and INVOKE by default treat initializers as unsigned.

Thanks, Michael. I also stumbled over this counter-intuitive behaviour some time ago, and am still looking for a plausible case where using IF with an unsigned integer (the default) would make any sensible difference to using it with a signed integer...

etow

Main Proc
  Local FactorString:Dword
  Local Factor:Dword
  ; FactorString is a string to store the accumulated characters to build up the string
  ; Factor is a number

  Mov FactorString, "1"
  Mov Factor, 2

  .while (Factor <= 20)
      Mov FactorString, cat$(str$(FactorString), chr$(" * "), str$(Factor))                     
      add Factor, 1
  .endw

  print str$(FactorString)   ; print out the accumulated string from the while loop

ret
Main EndP
---------------------------------------------------------------------
For the code above, is this the correct way to accumulate a string by building it up in a while loop and later printing it out?  Also, did I declare the variable for a string to accumulate correctly in the above code?

Please help.

Thanks

etow

hi

I have the updated code below
The code below is giving me an infinite loop

-------------------------------------------------------------------------------------------------------

.686 ; create 32 bit code

.Model flat, StdCall  ;32 bit memory model
Option CaseMap :none  ; case sensitive

Include   \masm32\include\windows.inc
Include   \masm32\macros\macros.asm       ; MASM support macros

  ; -----------------------------------------------------------------
  ; include files that have MASM format prototypes for function calls
  ; -----------------------------------------------------------------
Include   \masm32\include\masm32rt.inc

  ; ------------------------------------------------
  ; Library files that have definitions for function
  ; exports and tested reliable prebuilt code.
  ; ------------------------------------------------
IncludeLib   \masm32\lib\msvcrt.lib

.Code

start:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   Call Main
   inkey        ; pause the screen while waiting for user to press any key
                ; to continue
    exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Main Proc Uses Esi
   Local Number:DWord
   Local Remainder:DWord
   Local Quotient:DWord
   Local PrimeFactor:DWord
   Local Factor:DWord
   Local PrimeFactorBuffer[1024]:Byte
   Local primeCounter:DWord
   Local WantContinue:DWord
   ; Number is the integer to be factored
   ; PrimeFactor is the string containing the factored primes of the user's integer
   ; WantContinue is the sentinel value of the first while loop
    ;-----------------------------------------------------------
    Lea Eax, PrimeFactorBuffer
    Mov PrimeFactor, Eax
    Mov PrimeFactor, " "
    Mov WantContinue, 0

    .While ((WantContinue >= 0) && (WantContinue < -1))
       print chr$(13, 10)
       Mov Number, sval(input("Enter an integer value for Number : "))
       Mov Factor, 2
       Mov Esi, Number

       .If (Esi <= SDWord Ptr 1) ; if (Esi <= 1)
           print chr$(13, 10)
           print chr$("Invalid integer entered!", 13, 10)
           print chr$("An integer must be greater than 1!", 13, 10)
           print chr$(13, 10, 13, 10)
           Mov WantContinue, sval(input("Enter -1 to quit program : "))
           print chr$(13, 10)
       .ElseIf (Esi > 1)
           print str$(Esi)
           print chr$(" = ")
           Mov primeCounter, 1

         .While Factor <= Esi  ; Factor <= (Number = Esi)
             Mov Eax, Number
             Mov Ebx, Factor
             Cdq
             Div Ebx
             Mov Quotient, Eax   ; Quotient = Number / Factor

             Mov Eax, Number
             Cdq
             Mov Ebx, Factor
             Div Ebx
             Mov Remainder, Edx  ; Remainder = Number mod Factor

           .If (Remainder == 0)
               .If (primeCounter > 1)
                  print cat$(str$(PrimeFactor), chr$(" * "), str$(Factor))
               .ElseIf (primeCounter == 1)
                Mov Eax, Factor
                Mov PrimeFactor, Eax
                  print str$(PrimeFactor)
               .EndIf

               Mov Quotient, Esi   ; Quotient = Number = Esi             
               Mov Eax, Number
               Mov Ebx, Factor
               Cdq
               Div Ebx
               Mov Quotient, Eax   ; Quotient = Number / Factor

               Mov Eax, Number
               Cdq
               Mov Ebx, Factor
               Div Ebx
               Mov Remainder, Edx  ; Remainder = Number mod Factor
           .ElseIf (Remainder != 0)
              Inc Factor   ; Factor = Factor + 1
              Inc primeCounter
           .EndIf
           print chr$(13, 10)
         .EndW
         Mov WantContinue, sval(input("Enter -1 to quit program : "))
         print chr$(13, 10)
       .EndIf
    .EndW
    print chr$(13, 10)        ; a return key space will be outputted to the screen

  Ret
Main EndP

End start

--------------------------------------------------------------------------------------------
The code in red above I believe in giving me an infinite loop problem

I get an infinite display loop above
The following are examples of my input.

If I enter 2 for Number I get the following:

2
2
2
2
2
2
2
2
2
.
.
.
.
more 2's displayed to infinity

if I enter 3 for Number I get the following

32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
32 * 3
.
.
.
.
.
.
more "32 * 3" 's displayed to infinity

if I enter 23 for Number
I get empty space displayed to infinity
<blank space>
.
.
.
.
.
.
.
.
<blank space>

MichaelW

This applies to your Reply #6 post:

Your code is not allocating a buffer to hold the string. To create a local string, 100 bytes in length, you can use something like this:

Local FactorString[100]:BYTE

The cat$ macro requires that the buffer contain a null-terminated string, or that the first byte be set to zero to indicate that the string is empty. To set the first byte to zero you can use an instruction like this:

mov  FactorString, 0

Then you can use the cat$ macro to set the first factor in the string. Note that there are other, more efficient ways of doing this, but they are harder to understand. Note also that there is no need here for a separate variable to hold the address of the string buffer, because in the code you can just use "ADDR FactorString" to pass the address.  Note also that cat$ can accept quoted strings, and that there is no need here for the returned address, so this instruction just copies the returned address to a scratch register, effectively discarding it.

mov eax, cat$(ADDR FactorString, "1")

And in the loop, you could use something like this to add the factor to the string:

mov eax, cat$(ADDR FactorString, "*", str$(Factor))

And to print the string and move the text cursor to the next line, something like this:

print ADDR FactorString,13,10

Edit:

I think you need to avoid writing some large chunk of sloppy code, that repeats many of the same errors in your previous posts, and then dumping it on the forum expecting us to debug it for you. I think you don't understand how difficult it is to look at your code and understand what you are trying to do, and without understanding what you are trying to do, it's hard to know what is an error, and what is a side effect of some error. Before you went on to each succeeding post, you should have made sure that you understood the errors in your previous posts. The logic in your Reply #7 post is complex and hard to follow, and that means that it's likely to contain errors, and that the errors will be hard to find. There is a reason why experienced programmers generally don't write code like this.

Also, you should avoid posting the same question in more than one thread.

eschew obfuscation

RuiLoureiro

etow,
         1. I think the problem is in the  *** .While Factor <= Esi  *** loop.
            It never change. And Number never change. I think you dont want it.

         2. Why do you need to divide the Number again inside *** .If (Remainder == 0) ***

         3. Suppose Number=6. With Factor=2, the first division gives: Quotient=3 and
            Remainder=0.
            To the Next division, the Number should be Number=3=Quotient. NOT the same 6.
            Isnt it ? So ...
         
         4. To simplify your code
                 
         ;change this

        Mov Eax, Number
        Mov Ebx, Factor
        Cdq
        Div Ebx
        Mov Quotient, Eax          ; Quotient = Number / Factor

        Mov Eax, Number
        Mov Ebx, Factor
        Cdq
        Div Ebx
        Mov Remainder, Edx         ; Remainder = Number mod Factor


        ; by this

        Mov Eax, Number
        Mov Ebx, Factor
        Cdq
        Div Ebx
        Mov Quotient, Eax          ; Quotient = Number / Factor
        Mov Remainder, Edx         ; Remainder = Number mod Factor


                    EDIT:   read what MichaelW said

RuiLoureiro

jj2007

Quote from: MichaelW on January 25, 2008, 04:20:51 PM
Local FactorString[100]:BYTE
.. To set the first byte to zero you can use an instruction like this:
mov  FactorString, 0

Interesting. Since FactorString is BYTE, shouldn't the assembler move a single zero BYTE into FactorString? If yes, is that by design?

MichaelW

Yes, MASM knows the defined type, so it encodes the instruction as:

mov     byte ptr [ebp-64h],0
eschew obfuscation

jj2007

Quote from: MichaelW on January 25, 2008, 10:00:50 PM
Yes, MASM knows the defined type, so it encodes the instruction as:
mov     byte ptr [ebp-64h],0

Thanxalot - I keep learning  :toothy

etow

Hi

I understand my errors in the codes that I posted before in different posts.
I am learning from them.
I am sorry for my errors.


RuiLoureiro

Quote from: etow on January 26, 2008, 10:32:27 PM
I am learning from them.
I am sorry for my errors.

etow,
           Making errors is normal, dont give up. No problem.
           Did you solve your problem ? The limit ESI in the *** .While Factor <= Esi  ***  should be
           the current Number. The current Number should be the Quotient when Remainder = 0. No ?

RuiLoureiro