Hi everyone!
I, yet again, need your help! :(
Say I have the following code:
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
MyObj struct
MyVar1 DD 0
MyVar2 DD 0
MyVar3 DD 0
MyObj ends
MyObjPTR TYPEDEF PTR MyObj
MyThread proto :DWORD
.data
g_MyObj MyObj { 0, 0, 0 }
.code
start:
MOV g_MyObj.MyVar1 , 1
MOV g_MyObj.MyVar2 , 2
MOV g_MyObj.MyVar3 , 3
invoke CreateThread, NULL, 0, ADDR MyThread, ADDR g_MyObj, 0, NULL
CMP EAX, 0 ;Did we get a thread handle, if not jump to exit
JE Exit
MOV EBX, EAX ; store thread handle in EBX
invoke WaitForSingleObject, EBX, INFINITE ;Wait for thread to exit
invoke GetExitCodeThread, EBX, ADDR g_dwSuccess ;What was returned by the thread?
invoke CloseHandle, EBX
Exit:
invoke ExitProcess,eax
MyThread proc pData:DWORD
MOV EAX, [MyObj PTR pData].MyVar1
MOV EAX, [MyObj PTR pData].MyVar2
MOV EAX, [MyObj PTR pData].MyVar3
RET
MyThread endp
end start
When I debug this code I find the thread is created ok, but when it gets inside the thread the values that are moved into EAX are not the values I originally assigned to the global structure before I created the thread.
Any ideas why its is so?
Again your help is much appreciated.
The only thing I can see at first glance is your declaration of the MyObjPTR TYPEDEF which does not contain any space in the first word. And you include a space when you use it in your thread proc.
Raymond
I think you may have got a little confused. Get rid of the line MyObjPTR TYPEDEF PTR MyObj because you do not use it. Put this for your thread procedure:
MyThread proc pData:DWORD
assume pData:PTR MyObj
mov eax,[pData].MyVar1
mov eax,[pData].MyVar2
mov eax,[pData].MyVar3
assume pData:NOTHING
ret
MyThread endp
thanks for replying AeroASM, but now i get errors when I compile.
On the first ASSUME line I get:
error A2008: syntax error : pData
and on the MOV lines i get:
error A2006: undefined symbol : MyVar1
Please help!
Whoops, I was a little too hasty.
try this:
MyThread proc pData:DWORD
mov edx,pData
assume edx:PTR MyObj
mov eax,[edx].MyVar1
mov eax,[edx].MyVar2
mov eax,[edx].MyVar3
assume edx:NOTHING
ret
MyThread endp
Thanks AeroASM, that worked! :dance:
Now that I have a solution, I am wondering why it was a problem in the first place.
My Original code
MOV EAX, [MyObj PTR pData].MyVar1
Your code:
mov edx,pData
assume edx:PTR MyObj
mov eax,[edx].MyVar1
Firstly I am confused as to the position of the PTR in the ASSUME, which is before the 'type' MyObj, compared to the 'casting' in my code where PTR is after the 'type'.
My code compiles, but what exactly is it doing? I thought 'casting' pData to the type I want and then accessing the member of the structure would be acceptable? :dazzled: <--- we really need a scratching head icon.
hmmmmm.... any thoughts?
Looking at the dissassembled code:
Mine:
MOV EAX, [MyObj PTR pData].MyVar1
0040107F mov eax,dword ptr [pData]
AeraASM:
mov edx,pData
00401082 mov edx,dword ptr [pData]
assume edx:PTR MyObj
mov eax,[edx].MyVar1
00401085 mov eax,dword ptr [edx]
So whats the difference here? if in AeroASM code, EDX is pData, then my code"mov eax,dword ptr [pData]" is the same as "eax,dword ptr [edx]"
Hmmm, am I assumnig something I shouldnt be.....?
You've run into a limitation of the processor. It cannot use a pointer while it is still in memory. So it is necessary to move the pointer to a register.
The assembler simply reduces all the address components to form one valid addressing mode. The valid modes are immediate, register, and memory. The valid memory modes can be viewed as variations of the most complex addressing mode, [basereg + indexreg*scale + displacement]. There are limits to the addressing modes (e.g., scale can only be the constants 1, 2, 4, or 8). Valid memory modes cannot use a data pointer that's stored in memory. If the address references a pointer, it will simply use the pointer as data.
Or to put it another way...
mov eax,[MyObj PTR pData].MyVar1
has been reduced to
mov eax, [ADDROF(pData) + OFFSETOF(MyVar1)]
So, in quasi-C, you're getting pData.MyVar1 instead of (*pData).MyVar1.
aaaaah...I seee! :8)
so am I right in saying that
mov eax,[MyObj PTR pData].MyVar1
is getting the address off the stack and anding the offset of MyVar1? and thus moving a value in EAX that is relative to the current stack position and not relative to the value that pData holds?
I don't think that code will even compile. PTR does not mean pointer or anything else. It is just a random phrase, used in two places:
Where the size of a memory operand is otherwise unknown: dword ptr [ebx]
With the assume directive: assume edx:ptr MyObj
All the assume directive does is tell MASM that a particular register points to a kind of structure, so it knows what you are talking about when you ask it for MyVar1.
Quote from: Artoo on February 24, 2005, 12:07:06 AM
so am I right in saying that
mov eax,[MyObj PTR pData].MyVar1
is getting the address off the stack and anding the offset of MyVar1? and thus moving a value in EAX that is relative to the current stack position and not relative to the value that pData holds?
Correct, EAX is getting the pointer pData itself. When you try to get MyVar2 in the same way, you get the DWORD that follows the pData pointer.