News:

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

Declaring and Using Structures

Started by etow, February 21, 2008, 11:30:41 PM

Previous topic - Next topic

etow

Hi

I tried to understand the help MASM32 file about structures and wrote the following code below.
When I ran the program it gave me incorrect results and also it is a infinite loop.
Please help me.
Thanks


.686 ; create 32 bit code

;The MASM32 Runtime Library include file.
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Include \masm32\include\masm32rt.inc
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

.Const

PRIMENUMBER Struct
      Factor DWord 4 Dup (?)
      Power DWord 4 Dup (?)
      IsEvenPower DWord 4 Dup (?)
      IsOddPower DWord 4 Dup (?)
PRIMENUMBER EndS

.Code

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

Main Proc
Local WantContinue:DWord
Local counter:DWord
Local prme:PRIMENUMBER

; WantContinue is the sentinel value for while loop
    ;--------------------------------------------------------

    ; Eax, Ebx, Edx, and Esi are registers

   Mov WantContinue, 0   ; initialize WantContinue to zero

   Mov Eax, 1
   .While (Eax <= 20)
      Mov (prme[Eax]).Factor, 0
      Mov (prme[Eax]).Power, 0
      Mov (prme[Eax]).IsEvenPower, FALSE
      Mov (prme[Eax]).IsOddPower, FALSE
      Inc Eax
   .EndW

  .While ((WantContinue >= 0) && (WantContinue < -1))
  ; while WantContinue is greater than or equal to 0 And
  ; WantContinue is less than -1 do
  print chr$(13, 10)  ; a carriage return line feed will be outputted to the
                      ; screen

   Mov prme[1].Factor, 2
   Mov prme[1].Power, 4
   Mov prme[1].IsEvenPower, TRUE
   Mov prme[1].IsOddPower, FALSE

   Mov prme[2].Factor, 3
   Mov prme[2].Power, 1
   Mov prme[2].IsEvenPower, FALSE
   Mov prme[2].IsOddPower, TRUE

   Mov prme[3].Factor, 5
   Mov prme[3].Power, 6
   Mov prme[3].IsEvenPower, TRUE
   Mov prme[3].IsOddPower, FALSE

   Mov prme[4].Factor, 7
   Mov prme[4].Power, 7
   Mov prme[4].IsEvenPower, FALSE
   Mov prme[4].IsOddPower, TRUE

    print chr$(13, 10)

    Mov Eax, 1
    .While Eax <= 4
       print str$(prme[Eax].Factor)
       print chr$(13, 10)
       print str$(prme[Eax].Power)
       print chr$(13, 10)
       print str$(prme[Eax].IsEvenPower)
       print chr$(13, 10)
       print str$(prme[Eax].IsOddPower)
       print chr$(13, 10)
       Inc Eax
       print chr$(13, 10)
       inkey
    .EndW

    Mov WantContinue, sval(input("Enter -1 to quit program : "))
    Invoke ClearScreen ; clears the screen
  .EndW
    print chr$(13, 10)
    Ret
Main EndP

End start

MichaelW

You are getting an endless loop because the second while loop is using EAX as a loop counter, and the print macro (and the functions that it calls) does not preserve the value of EAX. So after the first call to the print macro the value that you loaded into EAX is lost. For something like this instead of EAX you should be using one of the registers that are preserved by the Windows functions and by the MASM32 macros and procedures. This normally means EBX, ESI, or EDI.

Once again, looking at your code it's hard to know exactly what you are trying to do, so it's hard to know how to reply. I'm going to guess that you want to work with an array of structures of type PRIMENUMBER.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    PRIMENUMBER struct
      factor  DWORD ?
      power   DWORD ?
      isEven  DWORD ?
      isOdd   DWORD ?
    PRIMENUMBER ends 

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    call Main
    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Main proc uses ebx esi

    LOCAL pn[4]:PRIMENUMBER

    ; ---------------------------------------------------------------
    ; For this code there is no need to set the structure elements to
    ; 0, but if there were this is much easier than coding a loop.
    ; ---------------------------------------------------------------

    invoke RtlZeroMemory, ADDR pn, SIZEOF pn

    ; --------------------------------------------------------------
    ; For the destination operands in the code below, pn represents
    ; the base address of the structure array, the number in the []
    ; brackets is the offset of the array element from the base
    ; address, and the ".factor", ".power", ".isEven", and ".isOdd"
    ; represent the offsets of the structure members within the
    ; array element.
    ; --------------------------------------------------------------

    mov pn[00].factor,  2
    mov pn[00].power,   4
    mov pn[00].isEven,  TRUE
    mov pn[00].isOdd,   FALSE

    mov pn[16].factor,  3
    mov pn[16].power,   1
    mov pn[16].isEven,  FALSE
    mov pn[16].isOdd,   TRUE

    mov pn[32].factor,  5
    mov pn[32].power,   6
    mov pn[32].isEven,  TRUE
    mov pn[32].isOdd,   FALSE

    mov pn[48].factor,  7
    mov pn[48].power,   7
    mov pn[48].isEven,  FALSE
    mov pn[48].isOdd,   TRUE

    ; -------------------------------------------------------------
    ; To encode the addresses correctly, MASM must know what ESI is
    ; pointing to. Either of the following 2 methods will work.
    ; In the loops ESI holds the address of the structure array,
    ; and EBX is used as a loop counter.
    ; -------------------------------------------------------------

    xor ebx, ebx
    lea esi, pn
    .WHILE ebx < 4
      print str$([esi].PRIMENUMBER.factor),13,10
      print str$([esi].PRIMENUMBER.power),13,10
      print str$([esi].PRIMENUMBER.isEven),13,10
      print str$([esi].PRIMENUMBER.isOdd),13,10
      add esi, 16
      inc ebx
    .ENDW

    inkey

    ASSUME esi:PTR PRIMENUMBER
    xor ebx, ebx
    lea esi, pn
    .WHILE ebx < 4
      print str$([esi].factor),13,10
      print str$([esi].power),13,10
      print str$([esi].isEven),13,10
      print str$([esi].isOdd),13,10
      add esi, 16
      inc ebx
    .ENDW
    ASSUME esi:NOTHING
   
    ret
Main endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation

etow

Hi Michael,

In my program that you corrected, I was trying to create a structure each time a prime number is factored out in a positive integer greater than or equal to 2.

How would you create a large enough array of structures to call the array of structure each time a prime number is factored out? I think the maximum array of structures that I will create is eight.
It is hard to tell how many prime number factors there will be in each positive integer so a loop will be used.  How do you implement the loop n times?

For example, the positive integer 30030,
The prime number factors of 30030 are 2, 3, 5, 7, 11, and 13.
The prime factorization of 30030 = 2 x 3 x 5 x 7 x 11 x 13
In this example above, I would create array of structures six times since there are 6 different prime number factors

Another example, the positive integer 108
The prime number factors of 108 are 2, and 3
The prime factorization of 108 = 2 x 2 x 3 x 3 x 3  or  2^2 * 3^3  or  4 * 27
Only two array of structures will be created for the positive integer 108 because of two prime number factors.

-----------------------------------------------------------------------------------------------------------
what does "invoke RtlZeroMemory, ADDR pn, SIZEOF pn" mean and do?
what does "ASSUME esi:NOTHING" mean and do?
-----------------------------------------------------------------------------------------------------------

Thanks Michael

MichaelW

Quotewhat does "invoke RtlZeroMemory, ADDR pn, SIZEOF pn" mean and do

It calls the Windows RtlZeroMemory function, passing it the address and size of the local buffer pn. Buffers created by LOCAL are not initialized to any particular value. So in code where the buffer needs to be initialized, and where the buffer is more than about 8-12 bytes long, it's easier to call a function to do that than it is to write code to do that.

Quotewhat does "ASSUME esi:NOTHING" mean and do

ASSUME esi:PTR PRIMENUMBER tells MASM to assume that ESI holds a pointer to a PRIMENUMBER structure, and ASSUME esi:NOTHING cancels that assumption.

eschew obfuscation

etow

Hi Michael,

How do you use a MASM32 program to initialize the items of a record instead of manually setting the values to the items of a record when using a loop?

Please reply.

Thanks.

MichaelW

See Structures and Unions in the MASM Programmer's Guide, about half way down the page here.
eschew obfuscation

etow

Hi Michael,

Thanks for your help!

I figured out how to do it by your examples.