News:

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

I'm not understanding this

Started by Shooter, December 21, 2010, 07:38:17 PM

Previous topic - Next topic

Shooter

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
Never use direct references to anything ever. Bury everything in
macros. Bury the macros in include files. Reference those include
files indirectly from other include files. Use macros to reference
those include files.

ramguru

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

jj2007

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 for a short routine that initialises local variables to zero.

Shooter

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
Never use direct references to anything ever. Bury everything in
macros. Bury the macros in include files. Reference those include
files indirectly from other include files. Use macros to reference
those include files.

clive

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.
It could be a random act of randomness. Those happen a lot as well.

dedndave

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

hutch--

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
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

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.

dedndave

 :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...

Shooter

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)

Never use direct references to anything ever. Bury everything in
macros. Bury the macros in include files. Reference those include
files indirectly from other include files. Use macros to reference
those include files.

dedndave

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

Shooter

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
Never use direct references to anything ever. Bury everything in
macros. Bury the macros in include files. Reference those include
files indirectly from other include files. Use macros to reference
those include files.

dedndave

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

Shooter

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
Never use direct references to anything ever. Bury everything in
macros. Bury the macros in include files. Reference those include
files indirectly from other include files. Use macros to reference
those include files.