News:

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

local variables in .data block

Started by ASMManiac, February 29, 2012, 05:31:04 AM

Previous topic - Next topic

ASMManiac

I am trying to make 2 procedures within 1 file, each will have a .data variable with the same name.

My code looks like this:

PROC procA
.data
db var1 0
.code
.... code.....
procA ENDP

PROC proB
.data
db var1 0
.code
.... code.....
procB ENDP

I am basically trying to declare the variables in the .data segment as local to the proc it is in, but jwasm says the Local keyword must be used within macros.  How can I properly do this?

hutch--

It doesn't work like that, using either a DATA or DATA? section means that data is written to a specific part of the loaded file image where when you create a LOCAL the space for the data is allocated on the stack.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ASMManiac

okay, so is there some way to avoid the name-mangling?

hutch--

What name mangling, neither DATA nor DATA? do this and local variables are purely an address on the stack.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

ASMManiac

I understand how everything in data is static and is referenced as a memory address at runtime,
what I am trying to do is allow 2 processes in the same file to use the same name for elements in the .data
I would like the assembler to generate code similar to this:

.code
procA proc
.data
var1 db 0
.code
xor rax,rax
procA  endp

procB proc
.data
var1Dummy db 0
.code
xor rax,rax
procB  endp
end



When I give it this:

.code
procA proc
.data
var1 db 0
.code
xor rax,rax
procA  endp

procB proc
.data
var1 db 0
.code
xor rax,rax
procB  endp
end

Instead, it complains that var1 has already been used.  I want to tell the assembler to identify the "local" var1 as a unique name in each PROC

donkey

Hi ASMManiac,

Your confusion is probably caused by a misunderstanding of scope. A section (.data,.code,.const etc...) holds global labels, that is they are available to the entire program and must have a unique name. When you use the .DATA directive whether its inside a procedure or not, the labels in that section will be global in scope, all the .DATA sections will be merged together when you build your program so every label must be unique. Locally scoped labels are unique to a procedure and the labels can be reused by other procedures, the only thing is that because the exact address of the label cannot be known at build time you cannot assign a value to the label. This is because the label is really just allocated space on the stack and is addressed as an offset from the current stack pointer (ESP). Since there is no way MASM can determine the value of the stack pointer at build time, it cannot fill the bytes your label is referencing with any values. You will have to assign the values at run time, in your example:

procA PROC
LOCAL var1:DB
mov var1,12345
.... code.....
procA ENDP

procB PROC
LOCAL var1:DB
mov var1,12345
.... code.....
procB ENDP


There are various tricks and macros to fill multiple locals quickly, Jochen wrote a nice one as far as I remember but for a single label you can just use MOV.

It is important to remember that local labels point to the stack which might contain data from other procedures that has been retired (ie is no longer valid) so you cannot count on it being the same in any two calls to your procedure, always assume that it contains random data that you have to initialize before using.

Edgar
"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

ASMManiac

Hi Edgar,
Thanks for that explanation.
I had trouble getting that syntax to work for creating the local variables

using: "LOCAL var1:DB"
I got "syntax error: db"

I was able to assemble the command using
var1 db 0

But
"local var1 db 0"
gave the eror "Expecting comma"

I tried the comma in a bunch of places but none worked.
Any ideas how to fix the syntax?

Also, If i understand you correctly, the local variables will the relative to the stack pointer.  So, if I push more stuff onto the stack later wouldn't that cause the local variable pointers to be incorrect?

BogdanOntanu

Try using this kind of syntax:


my_proc PROC
LOCAL my_local_var1 :DWORD
...
ret
my_proc ENDP


The local variables are referenced on stack but normally they refer relative to EBP and EBP is setup during PROC prologue code. Because of this you can PUSH / POP and alter ESP and your local variables are safe as long as you do not change EBP.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

jj2007

Hi AsmManiac,

If I understood right you want to use the LOCAL syntax with identical variables for two different procedures. That is feasible, although, as others have pointed out, not exactly a standard technique. Below an example, full code attached.

invoke MyTestA, offset AppName
invoke MyTestB
...

MyTestA proc arg1x:DWORD
LOCAL MyDw1, MyDw2, MyRect:RECT
  push ebp
  mov ebp, offset dummy
  arg1 equ dword ptr [esp+8]
  print arg1
  print str$(MyDw1), 9, " is MyDw1", 13, 10
  print str$(MyDw2), 9, " is MyDw2", 13, 10
  print str$(MyRect.left), 9, " is MyRect.left", 13, 10
  print str$(MyRect.top), 9, " is MyRect.top", 13, 10, 10
  mov MyRect.top, 12345 ; we change some values
  dec MyRect.left
  inc MyDw1
  dec MyDw2
  pop ebp
  retn 4 ; very important: retn 4*#args
MyTestA endp

MyTestB proc
LOCAL MyDw1, MyDw2, MyRect:RECT
  push ebp
  mov ebp, offset dummy
  print str$(MyDw1), 9, " is MyDw1", 13, 10
  print str$(MyDw2), 9, " is MyDw2", 13, 10
  print str$(MyRect.left), 9, " is MyRect.left", 13, 10
  print str$(MyRect.top), 9, " is MyRect.top", 13, 10, 10
  pop ebp
  retn ; retn 4*0
MyTestB endp


The "locals" are prefilled in the .data section and give the following output:

Masm32 is great!
1234     is MyDw1
5678     is MyDw2
12       is MyRect.left
34       is MyRect.top

1235     is MyDw1
5677     is MyDw2
11       is MyRect.left
12345    is MyRect.top

sinsi

> allow 2 processes in the same file to use the same name for elements in the .data
So same name but different vars in the .data section?

.386
.model flat,stdcall

.data
proc1var dd 0
proc2var dd 0

.code
proc1 proc
    var1 = proc1var
    mov eax,var1
    ret
proc1 endp

proc2 proc
    var1 = proc2var
    mov eax,var1
    ret
proc2 endp

start:  ret
end start

Light travels faster than sound, that's why some people seem bright until you hear them.

ASMManiac

Thanks, that worked.
So the assembler automatically makes reference to rbp/ebp whenever you use local variables, and I should not use rbp/ebp in my computation?
At the start of my function I am pushing all the registers onto the stack, should I not push rbp/ebp?

The reason I have this question is I am making a function that does min and max filtering of an image (e.g. min value within 11x11 neighborhood around each pixel) and the code for doing min and max is almost identical.
Since the code is almost identical, I am making a macro with all the common code that takes in assemble-time variable DO_MIN, and I have IF-ELSE branches to determine which part is assembled based on DO_MIN.

For example, one code snippet is this:

minMaxFilt1_16AMacro MACRO      DO_MIN
.... code ....
IF DO_MIN EQ 1
        pminub xmm0, xmm7
ELSE
   pmaxub xmm1, xmm7
ENDIF
.... code ....
ENDM

I am then making the 2 processes simply by calling the macro with different values of DO_MIN

minFilt1_16A  PROC
    minMaxFilt1_16AMacro    1
minFilt1_16A  ENDP

maxFilt1_16A  PROC
    minMaxFilt1_16AMacro    0
maxMaxFilt1_16A  ENDP




Quote from: BogdanOntanu on February 29, 2012, 09:37:17 AM
Try using this kind of syntax:


my_proc PROC
LOCAL my_local_var1 :DWORD
...
ret
my_proc ENDP


The local variables are referenced on stack but normally they refer relative to EBP and EBP is setup during PROC prologue code. Because of this you can PUSH / POP and alter ESP and your local variables are safe as long as you do not change EBP.


GregL

Quote from: ASMManiacusing: "LOCAL var1:DB"
I got "syntax error: db"

That would have to be "LOCAL var1:BYTE".


donkey

Quote from: GregL on March 01, 2012, 03:24:07 AM
Quote from: ASMManiacusing: "LOCAL var1:DB"
I got "syntax error: db"

That would have to be "LOCAL var1:BYTE".



That was my mistake, I thought MASM allowed that syntax and don't have it handy to test with.
"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

GregL

Edgar,

I should have added that your example works with GoAsm and not with Masm.  :)

donkey

Quote from: GregL on March 03, 2012, 03:04:41 AM
Edgar,

I should have added that your example works with GoAsm and not with Masm.  :)


Nah, doesn't work with GoAsm either, it was a senior moment :)
"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