News:

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

with or without "addr" ?

Started by supercoollee, September 23, 2011, 01:59:37 PM

Previous topic - Next topic

supercoollee

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

dedndave

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

BogdanOntanu

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.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

hutch--

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

supercoollee

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.

dedndave

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

drizz

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







The truth cannot be learned ... it can only be recognized.

PBrennick

In an case. preserve eax before the invoke statement unless its contents are arbitrary.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

jj2007

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.

qWord

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])
FPU in a trice: SmplMath
It's that simple!

GregL


hutch--

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

jj2007

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?

hutch--

 :bg

That's easy, disassembler kernel32.dll. It gets worse with later OS code, SEH, anti-hacking protection etc ....
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

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