I've tried using this form of accessing a struct via a pointer in a function...the values appear to remain correct inside of the function, but are incorrect after leaving the function:



.DATA
Struct STRUCTNAME <>

.CODE
proc1 PROC pStruct:DWORD
mov (STRUCTNAME PTR [pStruct]).structField, 12345
; Here the struct values are correct
ret
proc1 ENDP

proc2 PROC
INVOKE proc1,ADDR Struct
; Here the struct values are _incorrect_
ret
proc2 ENDP

,where "STRUCTNAME" is the name of the structure

When I changed the form to this, though, it worked perfectly:



.DATA
Struct STRUCTNAME <>

.CODE
proc1 PROC pStruct:DWORD
mov ebx,pStruct
mov (STRUCTNAME PTR [ebx]).structField, 12345
; Here the struct values are correct
ret
proc1 ENDP

proc2 PROC
INVOKE proc1,ADDR Struct
; Here the struct values are still correct
ret
proc2 ENDP


Why does the second form work, but not the first? Also, is this the best way to access a struct using a pointer in a function, or is there a better way?

/edit: made the code a bit more clearer
Posted on 2003-07-06 20:31:29 by sirchess2
Check to see if the first one is using ebp or esp as the register. The values of these will change on proc entry/exit. Esp will always change, ebp I think only somethimes.

Also, is this the best way to access a struct using a pointer in a function, or is there a better way?


Its the best way I've found. And a call to a function pointer only takes 3 bytes. Using an adress takes 5 or 6? :confused:

Using +index(what you are doing) allowes you to cast any memory pointed to by the reg to your struct. Very flexible.
Posted on 2003-07-06 21:47:31 by ThoughtCriminal
Why does the second form work, but not the first?


the first form doesn't really write to the structure.
You pass the adress to the structure onto the stack and then just write over the stack.



proc1 PROC pStruct:DWORD
mov (STRUCTNAME PTR [pStruct]).structField, 12345
ret
proc1 ENDP

the move instruction will become something like:
>>mov dword ptr , 12345
which means that 12345 is just written to the stack.
But, if you do as in the 2:nd form
>>mov ebx,pStruct ,
ebx will contain the adress to the structure so
>>mov (STRUCTNAME PTR).structField,12345 will become
mov dword ptr ,12345
where ebx is the actuall adress of the structure.

....I think :grin:

/edmund
Posted on 2003-07-06 22:07:45 by edmund
Edmund is correct.

Your first code only modify the value in which used to be the offset to the struct. However in your second code, the value in (first parameter) is moved to ebx. Thus you can use ebx as a pointer to access your struct.
Posted on 2003-07-06 22:23:42 by roticv
Thanks!

When you explain it like that, Edmund (and roticv), it makes sense to me, but it still seems weird just looking at the syntax that the effect of the code would be entirely different. I think I was/am a bit confused on pointers in assembly...is there no way, then, to dereference a pointer from a memory location without using a register?
Posted on 2003-07-06 22:31:02 by sirchess2
Dereference? Hahaha... mov pointer, 0 :grin:
Posted on 2003-07-07 00:30:13 by roticv
:confused:

Maybe I used the wrong terminology :grin: (I AM a former C/C++ coder...)

What I meant was, do I always have to put a pointer into a register to mov to and from the location the pointer points to...

Must I do this:
mov eax,pointer
mov ,value

Or can I do something to the effect of this:
mov ,value
Posted on 2003-07-07 10:18:20 by sirchess2
The line

mov ,value

will change the value of the pointer not the data it is pointing to. Also, since is in effect a memory address, "value" must be either a register or immediate. If it is immediate some assemblers will require that you supply the size of the data being mov'd to it i.e.

mov ,BYTE PTR 19

If value is a memory operand you must first mov the value into a register and then into

mov eax,
mov ,eax

To access the dereferenced location in memory that is pointing to you must use a register as you have shown. Be aware however that a dereferenced register is actually a memory operand so:

mov eax,
mov ,value

will only work as long as "value" is not another memory operand (i.e. a register or immediate)
Posted on 2003-07-07 10:43:44 by donkey
Thank you, Donkey

I knew that the mov instruction was incorrect, but I was more concerned with having my question understood clearly after roticv's last post :grin:

You answered what I needed to know though...i have to use a register to "access the dereferenced location in memory that is pointing to"

One more question (to test your patience :) )...what's the difference, then (if any), between "pointer" and ""?
Posted on 2003-07-07 10:53:11 by sirchess2
In MASM there is none as it assumes the [], in most other assemblers using pointer instead of is not allowed and will generate an error.
Posted on 2003-07-07 11:00:00 by donkey
Technically in masm brackets around variables do not matter. But I see brackets as memory. So if I tend to see


mov eax, pointer; as mov reg, immediate

and
mov eax, [pointer]; as mov reg, pointer/memory

But of course it is different on masm.

You see, your dword pointer contains a pointer to the data. Thus you cannot directly access the pointer to the data. (ie when you do mov ,eax it is the same as mov [403011], eax (an example). When you access the data in pointer, you access it as a pointer. ) Thus when you mov reg,pointer , you are actually moving the value in pointer to reg.

For example eax has the pointer to the dword pointer. (Using the same 403011 as the example given above)


mov eax, [eax] ; eax = pointer to data
mov [eax], immediate/reg ; moving data to the block of data/structure.


Hopefully you understand what I mean, though I may make it sound worse :).
Posted on 2003-07-07 11:06:22 by roticv
Hi roticv,

You are far too advanced in assembler to explain the basics :grin:

I tend to differentiate between a pointer and a label, a pointer can be directly accessed and modified while a label cannot...

Just remember that dereferencing (using the location pointer to not the value of the pointer) is not allowed except when using a register to dereference. pointer and are absolutely the same thing in masm but most other assemblers require that you include the []. Here's a demonstration:

MyData dd 9999
pMyData dd 0

Now point pMyData to the memory location of MyData, these are the same thing:

mov pMyData,OFFSET MyData
mov ,OFFSET MyData

To write to MyData using the pointer you must do this:

mov eax, (or mov eax,pMyData - they are the same in masm)
mov ,DWORD PTR 0 (you must specify the size of the operand here)
Posted on 2003-07-07 11:17:23 by donkey
Ahh ok i get it...So I should probably use even though it's the same in masm, just in case I ever decide to learn other assembly syntax.

Thanks to both of you :)
Posted on 2003-07-07 12:04:45 by sirchess2
I just remembered how to access the structure without a register.

Let the structure be


strcut struct
dword1 dd ?
dword2 dd ?
dword3 dd ?
strcut ends

To access the structure, just use the following
mov [strcut+4], eax ; dword2

mov ebx, [strcut+8]; dword3
mov [strcut],ebx;dword1


Not too sure, untested.
Posted on 2003-07-08 06:57:28 by roticv
You would have to declare the structure in the .data or .data? segment. Since defining the structure does not actually allocate memory to it there is no place to store the information. You can just use this :

strcut struct
dword1 dd ?
dword2 dd ?
dword3 dd ?
strcut ends

.data?
teststrcut strcut <>

.code
mov teststrcut.dword1,eax
mov eax,teststrcut.dword2
Posted on 2003-07-08 09:44:50 by donkey