News:

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

offset and ptr

Started by allynm, July 21, 2009, 01:43:01 AM

Previous topic - Next topic

allynm

hello everyone -

Yes, indeed, you will know my knowledge level by my questions.  I am trying to understand what conditions require the PTR (Word, Dword, Byte, etc.) operator and the OFFSET operator.  I know this is trivial stuff for all of you experienced folks, but I honestly don't understand when these two operarators are required.  If someone could clarify, i would be most grateful.  My experience previously is with NASM (in which they do not appear as such) and the need for these two operators remains unclear even after reviewing the help files in MASM and also the various procs and library items in the MASM distribution.  A lot of NASM comes over (and a lot doesn't!) and these two don't, at least as coded.


Regards to all,
Mark Allyn

GregL

allynm,

Have you looked at the MASM Programmer's Guide?, specifically Chapter 3 - Using Addresses and Pointers.


allynm

Hi Greg -

No, I hadn't, primarily because I was unaware the guide existed.  I have been working off the distribution itself, unaware of the existence of the guide.  Thanks to you, I am now aware of the guide and have looked at the ptr operator.  Haven't looked yet at the offset operator.  I remain confused by the guide's explanation of the ptr and when specifically it is required but will soldier on.  Thanks for the help.

Mark

MichaelW

#3
Perhaps this wll help.

; suntax: type PTR expression
; Forces the expression to be treated as having the specified type.

dwvar dw 0                  ; declared type is WORD

mov al, ddvar               ; error, operands not same size

mov al, BYTE PTR ddvar      ; no error, src operand is low-order byte
mov al, BYTE PTR ddvar+1    ; no error, src operand is high-order byte

dqvar dq 0                  ; declared type is QWORD

mov eax, ddvar              ; error, operands not same size

mov eax, DWORD PTR dqvar    ; no error, src operand is low-order dword
mov edx, DWORD PTR dqvar+4  ; no error, src operand is high-order dword

; syntax: OFFSET experssion
; Returns the offset address of expression (at assembly time).

ddvar dd 0              ; space for ddvar allocated at assembly time

mov eax, ddvar          ; src operand is value of ddvar (MOV accum,mem)

mov eax, OFFSET ddvar   ; src operand is address of ddvar (MOV reg,immed)

LOCAL locdd:DWORD       ; space for locdd allocated on stack at runtime

mov eax, locdd          ; src operand is value of locdd (MOV reg,mem)

mov eax, OFFSET locdd   ; error, invalid operand for OFFSET (offset
                        ; address not know at assembly time)

lea eax, locdd          ; src operand is the address of locdd on the
                        ; stack, expressed as something like [ebp-4]


; One method of accessing the members of a structure by
; name as indirect memory operands is to use the ASSUME
; directive and prefix the type field with PTR.

mov ebx, OFFSET rc
ASSUME ebx:PTR RECT
mov eax, [ebx].left


; The high-level decision directives by default perform
; unsigned comparisons. To force signed comparisons use
; signedtype PTR.

mov eax, -1
.IF eax < 0             ; expression will be false
.ENDIF
.IF SDWORD PTR eax < 0  ; expression will be true
.ENDIF



I see now that I left out some other less common uses for PTR.

Edit: added what I left out.
eschew obfuscation

NightWare

PTR (associated with a size or a structure) is used to indicate to the assembleur the operation to apply (it's essentially for a quick control of the validity of the use of the instruction). not always needed for masm 7-, it's generally needed for masm 8+. it correspond to size of data.

OFFSET/ADDR give to the assembleur a relative memory location (no size required here), however it's only usefull at compile time... it correspond to an address.

hutch--

Mark,

In MASM the two operators are manually specified so that you know exactly what they do.

An OFFSET is a location relative to a known reference point, in the case of a 32 bit PE executable file, it is from its start address when loaded into memory and it is used for data location in either the initialised .DATA section or the UNinitialised .DATA? section. It can also be used for code locations determined by a label in code as all of this information is available to the assembler at assembly time.

The PTR operator serves to specify the SIZE of the data it points to, literally stored the address of and it is used in MASM to avoid ambiguity for the actual instruction being used. If you have a memory address,


[ebp+16]


You don't know the size of the data at that address.


movzx eax, BYTE PTR [ebp+16]


Here you specify the size of the data so that MASM knows the size of the data to be zero extended into EAX.

Note that an ADDRESS pointed to by the PTR operator is always DWORD 32 bit in size in 32 bit code. In the old 16 bit DOS code an address is WORD sized (16 bit).
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

gwapo

Hutch,

I've seen from several examples that you can also use PTR as a pointer to struc when declaring an argument:


SomeStruc struc
  Member1 dd ?
  Member2 dd ?
SomeStruc struc

.code

TestProc proc lpStruc:PTR SomeStruc
  ret
TestProc endp


In the code above, what do I expect to be the size of lpStruc? Is it a DWORD size?

Thanks,

-chris

jj2007

Quote from: gwapo on July 21, 2009, 06:29:00 AM

I've seen from several examples that you can also use PTR as a pointer to struc when declaring an argument:


Me curious, too. Example below assembles fine but I get an access violation...

include \masm32\include\masm32rt.inc

MyProc PROTO: PTR SomeStruc

SomeStruc STRUC
  Member1 dd ?
  Member2 dd ?
SomeStruc ENDS

.data?
mys SomeStruc <?>

.code
start:
mov mys.Member1, 123
mov mys.Member2, 456
invoke MyProc, offset mys
exit ; short form of invoke ExitProcess, 0

MyProc proc MyPtr:PTR SomeStruc
  print str$(MyPtr.SomeStruc.Member1)
  ret
MyProc endp

end start

japheth

#8
(I'm not Hutch, but I reply nevertheless. :) )

Quote from: gwapo on July 21, 2009, 06:29:00 AM
Hutch,

I've seen from several examples that you can also use PTR as a pointer to struc when declaring an argument:


SomeStruc struc
  Member1 dd ?
  Member2 dd ?
SomeStruc struc

.code

TestProc proc lpStruc:PTR SomeStruc
  ret
TestProc endp


In the code above, what do I expect to be the size of lpStruc? Is it a DWORD size?

No, the size is 8 of course. [edit: Sorry, I misread, the size of lpStruc is 4 for 32bit of course ]

The problem with PTR is that it's used in 2 different contexts:

- as a binary operator. Syntax is <type> PTR <expression>
- as a 'unary operator'. Syntax is PTR [ PTR | <type>]

(That's one of the famous and beloved Masm syntax ambiguities.)

The first usage is found in expressions, it's called 'type coercion' and changes the type of <expression> to <type>.

The latter usage can be found  in directives like PROC, PROTO, EXTERN[DEF]. It informs the assembler of the level of indirection.






gwapo

Japheth,

Thanks for the explanations  :U


JJ,

I think you need to use a register to hold the pointer passed in argument:


include \masm32\include\masm32rt.inc

MyProc PROTO: PTR SomeStruc

SomeStruc STRUC
  Member1 dd ?
  Member2 dd ?
SomeStruc ENDS

.data
  appTitle db "Assembly ROQ", 0
  mys SomeStruc <123, 456>

.code
start:
  invoke MyProc, offset mys
  exit ; short form of invoke ExitProcess, 0

MyProc proc MyPtr:PTR SomeStruc
  mov edx, MyPtr
  assume edx: PTR SomeStruc
 
  invoke MessageBoxA, 0, str$([edx].Member1), addr appTitle, MB_OK
  ret
MyProc endp

end start


Cheers,

-chris

hutch--

Tolerate me here, Mark's question came with the assumption that he was familiar with NASM that does not normally use MASM notation so the example with MOVZX was aimed at how MASM uses [datatype] PTR to specify the SIZE of the data item with an instruction that requires a si9ze specifier.

Now short of the RTFM approach which is hardly useful to a new member asking a technical question, I have not addressed the use of the operator PTR exhaustively as it has other notational uses based on its semantics of "pointing to an address" rather than just a pointer to a datasize at an address. The obvious is of course that in 32 bit code the address is always a 32 bit datasize.

MASM has LENGTHOF and SIZEOF operators to perform assembly time functions of datasize calculation of complex data types.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: gwapo on July 21, 2009, 07:33:41 AM
JJ,

I think you need to use a register to hold the pointer passed in argument:


Well, yes, that works, but I had hoped that there would be a more "beautiful" way to address the members. Here is a variant without assume:
MyProc proc MyPtr:PTR SomeStruc
  mov edx, MyPtr
  invoke MessageBoxA, 0, str$([edx.SomeStruc.Member1]), addr appTitle, MB_OK
  ret
MyProc endp


Both your and my variant work fine also with MyProc proc MyPtr:DWORD, of course.

Another variant is to pass the structure itself. It looks nicer but Olly reveals that the stack is overused ;-)

include \masm32\include\masm32rt.inc

SomeStruc STRUC
  Member1 dd ?
  Member2 dd ?
  Member3 dd ?
  Member4 dd ?
  Member5 dd ?
SomeStruc ENDS

MyProc PROTO:SomeStruc ; proto must come AFTER the struc definition

.data
  appTitle db "Assembly ROQ", 0
  mys SomeStruc <123, 456, 3, 4, 5>

.code
start:
  invoke MyProc, mys
  exit

MyProc proc MyPtr:SomeStruc
  invoke MessageBoxA, 0, str$(MyPtr.Member1), addr appTitle, MB_OK
  ret
MyProc endp

end start

hutch--

The main advantage of using a construction like,


MyProc proc MyPtr:PTR SomeStruc


Is that you can use the structure member names when addressing parts of the structure that had its address passed.

Passing the actual structure is as you have mentioned, it just places all of the structure members on the stack which means that stack is doing a lot more work than if the address is passed.

When I pass a structure address I usually pass it as a DWORD then use one of the notations to get its members but that is as much habit and practice as anything else.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

sinsi

MyProc proc MyPtr:PTR SomeStruc
The other thing is the type checking MASM will do when you INVOKE the proc. Try using
invoke MyProc,mys
This gives an 'argument type mismatch' error unless 'offset mys' is used. It makes you think about how you
pass parameters, and is a bit more descriptive if all you have is the PROTO definition and no actual code.

I've never actually tried passing a structure as a parameter, I always pass the address of it.
(Anyway, I always use push/push/call and not invoke  :bg which makes you think even more)
Light travels faster than sound, that's why some people seem bright until you hear them.

gwapo

Hmm, it never cross my mind that you can actually pass an entire structure as parameter. How does it look like without invoke?



  assume eax: PTR SomeStruc
  push [eax].Member5
  push [eax].Member4
  push [eax].Member3
  push [eax].Member2
  push [eax].Member1
  call MyProc



?

Cheers,

-chris