News:

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

Declaring Global Variables

Started by Don57, June 10, 2008, 03:10:43 PM

Previous topic - Next topic

Don57

I have been unable to find the correct syntax for declaring a global variable in Masm32. Any help would be appreciated. I declare rect Local in WndProc (LOCAL rect:RECT) for GetClientRect and it works fine, but I need to use the RECT data structure at the start of the program for a SystemParametersInfo call. If I declare it during the mainline, I get duplicate definition error, no suprise there. I obviously need a public def'n but can't find the syntax.

BogdanOntanu


my_byte db 0
my_word dw 0
my_dword dd 0
my_rect RECT <10,12,200,300>


... and so on ... (try to search harder)
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

hutch--

Don,

Data written to either the initialised OR uninitialised data sections are global in scope across the entire module. Just to expand Bogdan's example a little, try this.


.data?   ; uninitialised data
  var1 dd ?

.data    ; initialised data
  item1 dd 0
  txtbuffer db 128 dup (0)
  ptrbuf dd txtbuffer

    etc ....
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Have a look e.g. at \masm32\examples\exampl01\generic\generic.asm

Important to know:

include \masm32\include\masm32rt.inc  ; first line in your code, saves you all .586 .model etc declarations and loads important macros

.data?
MyNonInitVar dd ?  ; will be zero when program starts

.data
MyInitVar dd 123  ; will be 123 when program starts

MyProc proc
LOCAL MyLocal:DWORD  ; will be undefined when sub-program starts, i.e. you have to initialise it yourself

.if eax<0
  invoke MessageBox, 0,
  chr$("You will never see this because eax is unsigned by definition"),
  chr$("Hint:"), MB_OK
.endif

Don57

Perhaps It's a logic error on my part. I use LOCAL rect:RECT in WndProc, but I also need to use it in the mainline. As you probably know PUBLIC rect:RECT doesn't work. I suppose, I my mind I'm looking for a PUBLIC or GLOBAL statement to declare it at the start of the program. It's not data structure concepts that are giving me the problems just the syntax

jj2007

.data?
grc   RECT <>         ; global structure

MichaelW

#6
You can also change sections at any point in your code, so you could define a global from within a procedure with something like this:

xxx proc
  LOCAL rc:RECT
  ...
  .data
    grc RECT <>
  .code
  ... 
xxx endp


In this case grc would end up in the initialized data section so it would effectively be global, but for the variable to work with invoke it would need to be defined in the source somewhere above the invoke statement.
eschew obfuscation

Jimg

Michael-
Quote from: MichaelW on June 10, 2008, 05:41:58 PM
In this case grc would end up in the initialized data section so it would effectively be global, but the requirement that it be defined in the source before it is referenced would still apply.
Is this true?
I think the only thing that needs to be defined before use in Masm is anything referenced in an invoke.  For normal code and all other uses, masm will figure out what and where it is.  Invoke is the only brain-dead instruction.
This assembles properly:yyy proc
    mov eax, offset grc
    lea eax,grc
ret
yyy endp
xxx proc zzkk
  .data
    grc RECT <>
  .code
xxx endp



MichaelW

You're right, thanks. I should have analyzed my results further. In my test I was passing grc to the print macro, which indirectly used it in an invoke statement.
eschew obfuscation

BogdanOntanu

As a side notice: MACROs need to be defined before use and invoke is a kind of internal macro for MASM.

However such issues are far too advanced for Don's questions.

Global variables go in .data section (if initialized) or in .data? section (if not initialized).
Local variables are defined inside PROC (procedures) with the LOCAL keyword and are visible and exist only in PROC.
There is another form of LOCAL that is relevant only inside MACRO's but that is more advanced.

Yes you can define a global variables inside a PROC with that .data ... .code trick but it is not advised for beginners because they can get confused.

And there are PUBLIC and GLOBAL keywords in MASM but they refer to visibility of symbols in between modules. When a linker has to solve the symbols in multiple .OBJ modules it will use the PUBLIC or GLOBAL statements to help (similar to HLL languages). Again this isuue looks like being too advanced for Don right now.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

jj2007

Quote from: BogdanOntanu on June 11, 2008, 12:36:41 AM
Local variables are defined inside PROC (procedures) with the LOCAL keyword and are visible and exist only in PROC.

More precise: They exist inside PROC under their name; however, you can pass a pointer to a sub-proc, and will see that the variable "exists" outside the proc... full example attached.

LOCAL pinfo:PROCESS_INFORMATION
...
   lea ecx, pinfo
   call OneDown
  ret

OneDown proc
  mov eax, [ecx.PROCESS_INFORMATION.hProcess]
  ret
OneDown endp


[attachment deleted by admin]

donkey

I agree with Bogdan here, the best way for a beginner to declare global variables is in a structured way that is consistent and clear. Put the .DATA and .DATA? sections at the top of the program and all variables declared within them will be global in scope. When Don57 becomes more familiar with the concepts of scoping within MASM he can try some more advanced syntaxes but for now he should stick to the clear and direct methods. For myself at least I always try to keep the declarations within the sections and avoid putting them in procedures etc... it makes the programs easier to read and debug and also helps in editing.

For jj2007, your assumptions about LOCALs being visible to other procedures is a little misleading. As you realize the stack is not reset until a procedure is completed so the pointers are still valid. Since LOCAL and GLOBAL refer to labels and not addresses because addresses are determined at run time (especially stack based ones) the LOCAL variable is *NOT* visible to the external subproc but it's address and data are valid. Bogdan was completely correct when he said it exists only inside the PROC since the subproc cannot guarantee the integrity of the data the local contains. It is only a property of the stack and addressing mode that makes the data available to subprocs.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on June 11, 2008, 06:53:54 PM
For jj2007, your assumptions about LOCALs being visible to other procedures is a little misleading. As you realize the stack is not reset until a procedure is completed so the pointers are still valid. Since LOCAL and GLOBAL refer to labels and not addresses because addresses are determined at run time (especially stack based ones) the LOCAL variable is *NOT* visible to the external subproc but it's address and data are valid. Bogdan was completely correct when he said it exists only inside the PROC since the subproc cannot guarantee the integrity of the data the local contains. It is only a property of the stack and addressing mode that makes the data available to subprocs.

it's address and data are valid
As long as you don't leave the calling PROC, its stack content is intact, and it's ok to pass pointers to it (as shown in the attachment). Supply an example where this does not work, and I will change my "assumption".

donkey

Quote from: jj2007 on June 12, 2008, 09:51:37 AM
it's address and data are valid
As long as you don't leave the calling PROC, its stack content is intact, and it's ok to pass pointers to it (as shown in the attachment). Supply an example where this does not work, and I will change my "assumption".

Actually it is difficult to think of one where it does work, GLOBAL and LOCAL refer to labels not specific areas on the stack, the label is not passed to the subproc even though the data it contains is still valid. Using the data by referencing it's address is simply a trick of the stack, not a use of a local label outside of the stack frame.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on June 12, 2008, 03:33:48 PM
Actually it is difficult to think of one where it does work,
see above

Quote
GLOBAL and LOCAL refer to labels not specific areas on the stack, the label is not passed to the subproc even though the data it contains is still valid. Using the data by referencing it's address is simply a trick of the stack, not a use of a local label outside of the stack frame.
I did not suggest to use the name of the label outside the PROC. I just said that these variables do exist and are valid outside the PROC, and that you just need another way to "see" them, e.g. by passing their address in ecx (as shown above) or in [esp+x]. This is what you and I do a hundred times in each project when using the word invoke...