The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: supercoollee on September 23, 2011, 01:59:37 PM

Title: with or without "addr" ?
Post by: supercoollee on September 23, 2011, 01:59:37 PM
i am still learning MASM+OPENGL.
when should there be "addr" or "offset" in front of a parameter in an INVOKE command?
i am confused  ::)
Title: Re: with or without "addr" ?
Post by: dedndave on September 23, 2011, 02:07:14 PM
ADDR should be used whenever the address of the variable needs to be calculated
this mainly applies to local variables
OFFSET should be used whenever it is a fixed address
        .DATA

szString db 'Hello World',0

        .CODE

Function PROC

        LOCAL   dwVariable:DWORD

        INVOKE  SomeFunc,offset szString,addr dwVariable
        ret

Function ENDP


the local variable is actually accessed by something like [EBP-4], so the ADDR operator should be used
Title: Re: with or without "addr" ?
Post by: BogdanOntanu on September 23, 2011, 02:07:25 PM
Use offset whenever you want the address of an item that is known at compile time, for example global strings or variables.

Use ADDR whenever your want the address of an item that has variable locations that can only be known at run-time. For example the address of an local variable on the stack.

Also note that ADDR usually generates an LEA EAX,[ebp +/- xxx] instruction and this trash EAX if you use for other tasks.
Title: Re: with or without "addr" ?
Post by: hutch-- on September 23, 2011, 02:07:35 PM
The difference between the CONTENT of a variable and WHERE it is. The notation ADDR in an invoke statement is WHERE the variable is in memory. An OFFSET refers to the location (WHERE) of a known address is that is created at assembly time.
Title: Re: with or without "addr" ?
Post by: supercoollee on September 23, 2011, 02:30:12 PM
can i say that it is also related to the invoked function? as some functions request an address, some functions request the content of an address?

still need some time to digest.
currently i am working on a small scale program and i use global variables mostly. i have no problem writing my own fucntions but when i invoke existing APIs, i need to swith on and off the "addr" to get it right.
Title: Re: with or without "addr" ?
Post by: dedndave on September 23, 2011, 03:47:19 PM
i understand perfectly   :bg

i had the exact same problem when i started out
i learned to read the MSDN documents carefully and to interpret the Hungarian Notation parameter names   :U
if the name refers to a pointer, it usually starts with "lp" or "p"
("p" means pointer, "lp" means long pointer - same thing in win32)
otherwise, it wants the value - not a pointer

a good example might be WriteFile
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx

BOOL WINAPI WriteFile(
  __in         HANDLE hFile,
  __in         LPCVOID lpBuffer,
  __in         DWORD nNumberOfBytesToWrite,
  __out_opt    LPDWORD lpNumberOfBytesWritten,
  __inout_opt  LPOVERLAPPED lpOverlapped
);


in particular, the lpNumberOfBytesWritten parameter
it wants the address of a dword variable that will receive the number of bytes written to the file
if it is a local variable, ADDR is appropriate

your remark about ADDR applying to INVOKE is not strictly correct
however, that is where you are most likely to see it

some notes on Hungarian Notation...
http://msdn.microsoft.com/en-us/library/aa260976%28v=vs.60%29.aspx
http://en.wikipedia.org/wiki/Hungarian_notation
Title: Re: with or without "addr" ?
Post by: drizz on September 24, 2011, 01:20:55 AM
It's simple really, ADDR is just an invoke helper macro,

addr xyz

If xyz Resolves To Offset use
  push offset xyz
else if it is a local varible use:
  lea eax, xyz
  push eax
else
  show error

you can use offset explicitly to indicate that xzy is not a local variable so it is clearer for anyone looking at your code.

also, a lot of times you will use eax and addr in invoke, sometimes you will  get an error "value of eax overwritten" if you remember my snippet from above you will know why.

while:
invoke myfunc, addr localvar, eax
will work,

this:
invoke myfunc, eax , addr localvar
will not







Title: Re: with or without "addr" ?
Post by: PBrennick on September 24, 2011, 02:33:15 AM
In an case. preserve eax before the invoke statement unless its contents are arbitrary.

Paul
Title: Re: with or without "addr" ?
Post by: jj2007 on September 24, 2011, 07:06:57 AM
Just in case you do have something important in eax:

mov eax, 123
lea edx, rc
invoke WhatEver, eax, edx   ; same as addr rc

This works because addr rc would be coded as

lea eax, rc
push eax

You can do the same explicitly wirh another register in order to spare eax from being ruthlessly destroyed.
Title: Re: with or without "addr" ?
Post by: qWord on September 24, 2011, 11:31:12 AM
Also a nice trick: use ADDR for calculating a function's parameter:
; create buffer for string psz
invoke invoke szLen,psz
invoke invoke GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT, ADDR [eax+1]
; the same as: alloc(ADDR [len(psz)+1])
Title: Re: with or without "addr" ?
Post by: GregL on September 25, 2011, 02:21:51 AM
I agree with drizz.
Title: Re: with or without "addr" ?
Post by: hutch-- on September 25, 2011, 10:55:33 PM
Something to keep in mind when you are calling high level functions like OpenGl or similar, there is no particular reason why you need to load the arguments into registers when normal memory operands work fine. The Microsoft reference material will tell you what is a VALUE and what is an ADDRESS and if you use LOCAL variables for the arguments you completely avoid the register overwrite problems.

Naming your variable according to what information they have in them makes your code a lot clearer and more reliable and you need only pick a naming scheme to do this.

Just as a suggestion you can do stuff like this.


LOCAL pMemory :DWORD  ; a POINTER to a memory address
LOCAL loopcounter :DWORD  ; a variable to contain the loop count VALUE


By writing the high level code in this format you have all of your registers available when you need to write high speed mnemonic code without any of the problems.


    invoke GlobalAlloc,bytecount etc etc ....
    mov pMemory, eax


Once you have the return value from GlobalAlloc() written to a POINTER you don't have to track the EAX register.

Once you have the code up and running reliably you can perform any close range optimisations you think will be useful but note that almost all high level functions are far slower than pure mnemonic code so there is often little gain by doing so.
Title: Re: with or without "addr" ?
Post by: jj2007 on September 26, 2011, 12:02:25 AM
Quote from: hutch-- on September 25, 2011, 10:55:33 PM
...but note that almost all high level functions are far slower than pure mnemonic code

Hey, that's new, can you give an example?
Title: Re: with or without "addr" ?
Post by: hutch-- on September 26, 2011, 12:13:03 AM
 :bg

That's easy, disassembler kernel32.dll. It gets worse with later OS code, SEH, anti-hacking protection etc ....
Title: Re: with or without "addr" ?
Post by: jj2007 on September 26, 2011, 07:40:20 AM
Quote from: hutch-- on September 26, 2011, 12:13:03 AM
That's easy, disassembler kernel32.dll. It gets worse with later OS code, SEH, anti-hacking protection etc ....

That makes it clearer, thanks. I confused "high level function" with "high level language elements" like .if/.endif, .Repeat/.Until etc, which are obviously as fast as the "pure" mnemonic code they produce. Perhaps it is better to clarify that in a Campus thread :wink