News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

addr vrs offset

Started by dc, May 24, 2024, 10:21:41 AM

Previous topic - Next topic

dc

i notice some folks (cant remember who now it's been a while) correct me for using addr instead of offset in certain instances, usually they seem to work the same, is there a reason to use one rather then the other? thanx

NoCforMe

Yes. They're not really interchangeable.
Use OFFSET when you (actually the assembler) knows the item you want the address of has a fixed address; this applies to variables declared in one of the .data sections:
.data
SomeVariable    DD ?

    MOV    EDX, OFFSET SomeVariable
ADDR is only used for variables that are either on the stack, or are pointed to by a register: in both cases, the item you want the address of has no fixed address.
  LOCAL  someVariable:DWORD, someOtherVariable:DWORD

  MOV    EDX, ADDR someVariable

  LEA    EDX, someOtherVariable  ;this is a pointer to a structure

  INVOKE  SomeFunction, ADDR someVariable, ADDR [EDX].someStructure.someElement
What happens behind the scenes when you use ADDR is this:
    LEA  EAX, <variable>
    PUSH  EAX
which is why you cannot use EAX as a parameter to the left of ADDR, because EAX will have been clobbered by ADDR.

o Use OFFSET when the address of the variable is known (global variables in .data or .data?);
o Use ADDR where the variable doesn't have a fixed (known) address (either a LOCAL variable on the stack or something pointed to by a register, like [EDX].STRUCT.element).

What you can't do is this (this will result in an assembler error):
XYZ    PROC
        LOCAL someVariable:DWORD

  MOV    EAX, OFFSET someVariable
because someVariable has no known fixed address (it's on the stack).

Assembly language programming should be fun. That's why I do it.

jj2007

You can use addr in most cases. However, while it is obligatory to use addr for local variables, for global variables you can use either addr or offset. In the interest of readability, it is good practice to use systematically offset for global variables, so that you can see at one glance whether a variable is local or global.

NoCforMe

Just did a test. No, you can't use ADDR in "most cases"; only where it's appropriate.

This will win you an error:
.data
SomeVariable  DD ?

.code
    MOV  EAX, ADDR SomeVariable

Use OFFSET here instead (globals in .data or .data?, remember?).

Further research: I thought you could only use ADDR with INVOKE, and it turns out I was right about that. From the MASM 6.1 manual:
QuoteThe ADDR keyword is new since MASM 5.1. When used with INVOKE, it
provides the address of a variable, in the same way as the address-of operator
(&) in C.
Assembly language programming should be fun. That's why I do it.

sinsi


_japheth

Here's an example where using "offset" causes a pretty hard to find error, while "addr" works fine.

Actually, it's a JWasm regression test case ( no windows proggie, sorry, not even a running program at all ).

;--- error with using offset in INVOKE

.386
.MODEL tiny, stdcall
.dosseg
.stack 2048
option casemap:none

_TEXT16 segment word use16 public 'CODE'

oldint8rm dd ?
oldint9rm dd ?

irq0rm:
iret
irq1rm:
iret
rmsetvecs:
rmresetvecs:
retf

_TEXT16 ends

.CODE

;--- setup rm irq procs

SetIVTVec proc uses ebx edi mode:dword, vec:dword, newvec:word, pOldVec:ptr
mov ebx, vec
mov edi, pOldVec
mov dx, newvec
ret
SetIVTVec endp

SetIVTVecs proc mode:dword
invoke SetIVTVec, mode, 8, offset irq0rm, addr oldint8rm
invoke SetIVTVec, mode, 9, offset irq1rm, addr oldint9rm
ret
SetIVTVecs endp

end

So .... who is  capable to find out what the problem is? It's a real aptitude test...
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

sinsi

OFFSET in the 32-bit code is only pushing the 16-bit offset , ADDR is pushing the 16-bit offset plus a WORD 0.
Stack misaligned by 2?
RET 10h fails?

daydreamer

I prefer use lea eax,variable
Instead of mov eax,offset variable
Like this
Princess:lea eax,Luke
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

_japheth

Quote from: sinsi on May 24, 2024, 03:42:08 PMOFFSET in the 32-bit code is only pushing the 16-bit offset , ADDR is pushing the 16-bit offset plus a WORD 0.
Stack misaligned by 2?
RET 10h fails?

Congrats, you're a member of the small group of people who knows when and how a listing is to be used!

It's actually another "Masm invoke" bug, IMO...
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

sinsi

Quote from: daydreamer on May 24, 2024, 03:49:01 PMI prefer use lea eax,variable
Instead of mov eax,offset variable
Like this
Princess:lea eax,Luke
The instruction can be a byte or two longer though, if that matters.
It's a good idea in 64-bit programming, never use OFFSET and you will have position-independent code (RIP-relative), no fixups/relocations.

jj2007

Quote from: NoCforMe on May 24, 2024, 11:15:12 AMNo, you can't use ADDR in "most cases"; only where it's appropriate.

Absolutely, that's what I meant but forgot to specify: with invoke

MOV  EAX, ADDR SomeVariable will throw an error, so no harm done.

Please, let's not forget that this is a Campus thread.

With 32-bit code, use:
mov eax, offset globalvar
lea eax, localvar
invoke someproc, offset globalvar  ; you can use addr globalvar, but for readability use offset
invoke someproc, addr localvar     ; you must use addr here

With 64-bit code, use:
lea eax, globalvar
lea eax, localvar
invoke someproc, addr globalvar
invoke someproc, addr localvar

NoCforMe

Quote from: jj2007 on May 24, 2024, 04:59:49 PMWith 64-bit code, use:
lea eax, globalvar
What, no OFFSET in 64-bit?

Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on May 24, 2024, 06:15:09 PMWhat, no OFFSET in 64-bit?
Yes, but it requires a relocation which is 8 bytes plus the instruction whereas ADDR uses RIP-relative addressing, so every offset is just RIP plus/minus a signed DWORD, 4 bytes plus instruction.

jj2007

  mov rax, offset globalvar
  lea rax, globalvar

64-bit:
0001_40001087    48:B8 3C30004001000000     mov rax,offset 0001_4000303C             ; ASCII "Ciao"
0001_40001091    48:8D05 A41F0000           lea rax,[rel 1_4000303C]                 ; ASCII "Ciao"

32-bit:
00401056  |.  B8 3C304000     mov eax, offset 0040303C                 ; ASCII "Ciao"
0040105B  |.  8D05 3C304000   lea eax, [40303C]                        ; ASCII "Ciao"

dc

thanx everyone... id call that comprehensive 8)