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?
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.
okay, so is there some way to avoid the name-mangling?
What name mangling, neither DATA nor DATA? do this and local variables are purely an address on the stack.
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
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
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?
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.
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
> 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
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.
Quote from: ASMManiacusing: "LOCAL var1:DB"
I got "syntax error: db"
That would have to be "LOCAL var1:BYTE".
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.
Edgar,
I should have added that your example works with GoAsm and not with Masm. :)
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 :)