I'm trying to build macro-like procs in my project (without passing variables), but I'm having difficulties with local variables.
In this excerpt I receive the errors below:
FindComputerName proc
.data
lpszComputerNameSubKey DB "SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName",0
lpszComputerNameValueName DB "ComputerName",0
LOCAL hKey:DWORD
.code
pusha
invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,addr lpszComputerNameSubKey,0,KEY_QUERY_VALUE,addr hKey
QuoteReadRegKey.asm(61) : error A2012: PROC, MACRO, or macro repeat directive must precede LOCAL
ReadRegKey.asm(70) : error A2006: undefined symbol : hKey
ReadRegKey.asm(70) : error A2114: INVOKE argument type mismatch : argument : 5
ReadRegKey.asm(74) : error A2006: undefined symbol : hKey
ReadRegKey.asm(74) : error A2114: INVOKE argument type mismatch : argument : 1
ReadRegKey.asm(77) : error A2006: undefined symbol : hKey
ReadRegKey.asm(77) : error A2114: INVOKE argument type mismatch : argument : 1
ReadRegKey.asm(84) : error A2006: undefined symbol : hKey
ReadRegKey.asm(84) : error A2114: INVOKE argument type mismatch : argument : 1
But in this excerpt the program compiles without warnings or errors, but crashes upon launch:
FindComputerName proc
lpszComputerNameSubKey DB "SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName",0
lpszComputerNameValueName DB "ComputerName",0
LOCAL hKey:DWORD
pusha
invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,addr lpszComputerNameSubKey,0,KEY_QUERY_VALUE,addr hKey
Would someone please explain what's going on to cause the errors / crash, and possibly the proper way to have local variables? (In that vain, is there a way of defining a local variable to a predetermined value? I.E. LOCAL lpdwReserved:DWORD:NULL)
Thanks,
-Shooter
local variables cannot be initialized instantly. It's just a higher-level trick that uses some extra instructions I'm sure.
.data section is created when compiling executable, whereas stack for local variables is allocated on request, therefore its content cannot be predetermined.
As for local string variable, you allocate one like this: LOCAL buf[64]:BYTE
You could also use text macros: invoke RegOpenKeyEx, .., CADD("sometext")
There are two types of LOCAL variables: Those in macros, in the first line after xxx MACRO, and those under the xxxx proc. The latter are simply a slot on the stack, and defined relative to ebp. You need Olly to see what exactly happens there. Alternatively, you could read the MASM programmer's guide ;-I)
Important: They will contain garbage on entry into the proc. See this post (http://www.masm32.com/board/index.php?topic=14150.msg112344#msg112344) for a short routine that initialises local variables to zero.
I'm a little fuzzy on what you mean about the strings.
I removed the lpsz variables and placed them in my global .data declarations. Then I deleted the .data and .code from my proc and left the local hKey:DWORD in the proc and all works again.
Can strings be defined within a proc?
Secondly, and I realize this may not be the correct sub-forum for this, but I'm using RadASM 3.x / MASM32 for this and I don't know how to include macros yet. Got any pointers?
-Shooter
Quote from: Shooter on December 21, 2010, 09:10:42 PM
Can strings be defined within a proc?
I'm sure you can do the DB thing you're doing now, but you need to put them after the RET or executable code, because at the front of the PROC where you are placing them now they turn into executable junk and your procedure will crash in the manner you observed.
strings can be defined as local variables, too - they jsut aren't initialized if you do it that way
there are other ways to place a string on the stack than by using LOCAL
Shooter,
You can do this in MASM if you want to define strings close to where you use them.
.data
mystring db "Hi, I am a string",0
pstring dd mystring
.code
invoke SomeFunction,pstring
Quote from: Shooter on December 21, 2010, 09:10:42 PM
Can strings be defined within a proc?
Yes and no. You can copy a global string to a local buffer as follows:
include \masm32\include\masm32rt.inc
.code
start:
call MyTest
exit
MyTest proc
LOCAL MyString[100]:BYTE
invoke lstrcpy, addr MyString, chr$("This was a global string but now there is a local copy")
MsgBox 0, addr MyString, "Test", MB_OK
ret
MyTest endp
end start
The source of the copy, chr$("This was a global string but now it is local"), however, is a globally defined string.
:P
.XCREF
.NOLIST
INCLUDE \masm32\include\masm32rt.inc
.586
.LIST
.CODE
;--------------------------------------------------
_main PROC
call BrandStr
inkey
exit
_main ENDP
;--------------------------------------------------
BrandStr PROC
push ebx
push edi
xor edi,edi
push edi
or edi,3
BrStr0: lea eax,[edi+80000001h]
cpuid
push edx
push ecx
push ebx
push eax
dec edi
jnz BrStr0
mov edi,esp
mov al,20h
mov ecx,48
repz scasb
dec edi
print edi
add esp,52
print chr$(13,10)
pop edi
pop ebx
ret
BrandStr ENDP
;--------------------------------------------------
END _main
see attached program...
So global strings within a proc aren't moved to the correct area during linking? I'd have to do this:
EndP
.data
str1 db "String 1",0
str2 db "String 2,0
proc MyProc
;code
EndP
Dave, I didn't quite understand the point of your example. (Sorry)
if you use .DATA or .CODE (etc), the assembler suspends assembly of the section you are in and assembles in the new section
so, if you have a proc in the code section, switch to the data section, then back again, everything winds up where it belongs
as for my example, i just wanted to show that there are a number of ways to put a string on the stack inside a proc
although, CPUID may not have been the best example, it is a cute little routine :P
Oh yeah, I forgot to put .code in my example. :red
I like that CPUID instruction... I need to read up on what else has been added since the early 90's. :wink
I'm currently writing subroutines in their own file that I can find multiple uses for, so knowing how to do this is a major plus.
Question though... If I were to build up a larger .asm file that holds multiple subroutines, but I only needed just a few of them, would the remainder of them get included in the final build? (I know I've got a separate thread on this, but this thread sort of lead up to it.)
-Shooter
if you put them in an INC file, they will be included :P
but, it is easy to convert them to OBJ files, then add them to your own static LIB
i made a simple example in the first post of this thread...
http://www.masm32.com/board/index.php?topic=15480.0
be sure to place the zip in the \masm32\examples folder so that the destination folder is named \masm32\examples\static
Dave,
I'm going to have to study up on .lib and .inc properties... it's been too long since I last did one, and the language has changed some and expanded since my days (DOS 6.22). "One line of code at a time."
Right now I'm just trying to get the hang of standard coding, which is why I asked about multiple .asm files and integrating them.
Thanks,
-Shooter