News:

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

Pointer training

Started by Don, February 24, 2006, 01:11:29 PM

Previous topic - Next topic

Don

Hi guys, I would like to get some (read "a lot of") help with pointers. Are there any training documents you can point [ :U] me at? I am specifically interested in figuring out the following problem but I would really appreciate some ground up reference on working with pointers.

I have a call to DeviceIOControl which fills a buffer. The structure to read that buffer changes depending on one of the values in the buffer (look at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/fsctl_get_reparse_point.asp for more information - "lpOutputBuffer").

How can I create the two different structures and then point them to the same buffer?

I look forward to any help you can give - this is driving me nuts.

Regards, Don.

donkey

In this case I load the pointer to the buffer into a register and use that to address the fields depending on the reparse tag.

mov edi, [lpOutBuffer]
mov eax,[edi] ; The first field is always the tag
cmp eax, MS_REPARSE_TAG ; Any Microsoft tag, this constant doesn't really exist
jne >
// REPARSE_DATA_BUFFER
mov eax,[edi+REPARSE_DATA_BUFFER.ReparseDataLength]
// Do your thing here

jmp >>.OUT

:
// REPARSE_GUID_DATA_BUFFER
// This is a GUID
mov eax,[edi+REPARSE_GUID_DATA_BUFFER.ReparseDataLength]
// Do your thing here

.OUT

"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Tedd

Pointers in assembly are so simple it's hillarious :lol
Forget all the nonsense that other languages impose on you (yes C++ I'm talking to you!) - a pointer is the address of something. That is it. That's all you need to understand.
So, a pointer to a buffer is exactly just the address of that buffer. And a pointer to a variable is the address of that variable.
Luckily, most (sane) people tend not to write directly in hex, so you don't need to worry too much about what the exact address or numbers are. There are helpful operators: ADDR and OFFSET to get the address of something for you.

So, for your DeviceIOControl function, lpOutputBuffer is a pointer to the buffer to receive the results of the function call. But, depending on the values passed to the function, this buffer will be treated in one of two ways. As far as the function is concerned, as long as the buffer is big enough, all buffers are the same (it's just a block of memory to store something in.) So for the lpOutputBuffer argument you would put "ADDR myBuffer" and nOutBufferSize is "SIZEOF myBuffer". For the function call, this is all fine and will work.
The small complication is in defining myBuffer so that a) it's big enough, and b) you can access it as whichever of the structures you choose to.
For this you'll need to look up how to define a structure (quite simple) and then how to define a union within a structure (again, not too difficult.) Once you have the structure defined, you'll have to find out how to access a 'typed' structure which is again straightforward.
I think you was just thinking about it the wrong way around - you don't create two buffers and point to both of them (you only have one 'arrow' so you can't point two ways,) you create one buffer and point to it, and then treat it in the appropriate way afterwards (since you already know how you want to treat it.)
No snowflake in an avalanche feels responsible.

Klod

I have been studying addressing and pointers for some time, but I am still missing something. I have come up with this piece of code that appers to work but as can be seen in Fillproc, it does not work the way I think it schould.
EditBoxProc proc
LOCAL buf [128]:byte
GLOBAL arrEdit dd 7 dup(0) ;array to store the handles
GLOBAL rc DD 10,0,90,18,10,23,90,18,10,46,90,18,10,69,90,18,10,93,90,18,10,116,90,18,10,139,90,18
GLOBAL hEdit dd ?

invoke GetDlgItem,hWnd,1001 ;Windows API result gets stored in eax
mov hEdit,eax
;mov arrEdit,dword ptr eax  ;is this the same as previous
push EBX
push ESI
push EDI   
ASSUME eax:PTR RECT
mov esi, offset rc        ; base address of tbl rc

    mov ebx,0
    top:
    cmp ebx,7 ;create 7 edit boxes

je lout
mov eax, esi ;offset rc
invoke CreateWindowEx,NULL,SADD("EDIT"),SADD(" "),\
WS_VISIBLE OR WS_CHILD,[eax].left,[eax].top,[eax].right,\
[eax].bottom,hWnd,NULL,hInstance,NULL
mov DWORD PTR arrEdit[ebx],eax
mov edx, DWORD PTR arrEdit[ebx] ;store handle in edx
push ecx
push edx
invoke dwtoa, edx, addr buf ;convert handle to string
pop edx
;invoke SendMessage,edx,WM_SETTEXT,0,addr buf ;display handle in edit box
invoke SendMessage,hEdit,LB_ADDSTRING,0,addr buf ;display handles in List box
add esi,16
inc ebx
jmp top
lout:
    assume eax:nothing
pop EDI
pop ESI
pop EBX
;
call FillProc
ret
EditBoxProc endp

FillProc proc
LOCAL buff [128]:byte
mov edx,offset arrEdit ;addr of arrEdit
push edx
fn MessageBox,hWnd,str$(edx),"EDX",MB_OK
pop edx
xor ecx,ecx
;inc ecx
mov edx,[edx+ecx*4] ;should be value stored at arrEdit[0]
fn MessageBox,hWnd,str$(edx),"EDX",MB_OK
push edx
invoke dwtoa, edx, addr buff ;convert handle to string
pop edx
invoke SendMessage,edx,WM_SETTEXT,0,SADD("Caption changed") ;should add text to list box 1
invoke SendMessage,hEdit,LB_ADDSTRING,0, SADD("Test string") ;this should add test string in 1st edit box
ret
FillProc endp


I played arround for quite some time trying to get the right handle to the editboxes, but without success. What I am doeing wrong?
Any help would be appreciated :red

Don

whoosh.........slap!

That was the sound of your advice going straight over my head and hitting the wall behind me.

Please give me some pointers to pointer training articles. I want to start at 101.

Regards, Don.

P1

Don,

Welcome a Board !!!      :U

Forum 'Search' is your friend, along with Google.   

Have some fun with this.
Start here and work back to us:
http://webster.cs.ucr.edu/AoA/index.html

Have you installed MASM32 package yet?
If you have, go through the ICZTUTES, then the other example folders.

Regards,  P1   :8)



Don

Hi P1, I am from the dos days. I know my way around bits of assembler but pointers are somerthing that really confuse me. Yes I do have Masm32 installed (Brilliant Steve!) and I have the manuals for the last masm I ever played with in front of me (5.1) but I still would love to get some info on pointers (in the 5.1 manual ther are 2 index entries which are "defining" and "loading" -- got the idea  :bg)

Regards, Don.

Mark Jones

Hi Don, welcome to the group. :)

Please, open up the \masm32\help\ASMINTRO.HLP file. Look under the "addressing and pointers" topic. Have fun! :wink
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Don

Hi Mark, very happy to be here (thanks for the welcome)

I'm sorry but the help file doesn't make it any clearer.

I have a buffer and a couple of structures (records?):

.data
myByffer db 20 * 1024
lpRDBms dd REPARSE_DATA_BUFFER
lpRDBgui dd REPARSE_GUID_DATA_BUFFER

How do I get to the memory in myBuffer via lpRDBms and lpRDBgui?

I want to use lpRDBms and lpRDBgui to point to myBuffer so that after has been filled with data I can read the data in the buffer using the structure syntax (mov lpRDMS.something, eax)

I really hope I have made myself clear this time  :red

D.

donkey

Hi Don,

If you check my post it shows you how this is done, there is no need to create the other 2 buffers, just put the address of MyBuffer in a register then use the method I posted above to address the buffer using whatever structure definition you choose. Your problem is not so much understanding pointers as it is understanding exactly what a structure resolves to. In effect a structure member only resolves to a number so for example..

RECT struct
left DD ?
top DD ?
right DD ?
bottom DD ?
RECT ENDS

resolves to

RECT.left = +0
RECT.top = +4
RECT.right = +8
RECT.bottom = +12

but so will any other structure, for example...

POINT.x = +0
POINT.y = +4

so in reality RECT.top and POINT.y are completely interchangeable as they both just resolve to +4. We use RECT in order to make the code more readable but all it boils down to is an offset from the beginning of the structure. So when you move the pointer into say EDI, you can add either of the structures to it, it makes no difference. The only time it makes a difference is if you use a structure that has been decalred in either the .DATA or .DATA? section, then the assembler will also add the offset in that section. So in your case move the offset to MyBuffer into EDI and use the structure you need to address the data (in whatever format) in that buffer...

mov EDI, OFFSET MyBuffer
mov eax, [EDI+REPARSE_GUID_DATA_BUFFER.ReparseDataLength]

And everything will be fine.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Don

Hi Edgar,

Is there no way that I can make the structure point directly to the buffer?

no eax, no nothing -  can I point lpRDBms and lpRDBgui directly at the first byte of rbuffer and use whichever structure I prefer?

Sorry if this seems dense but I did ask for pointer 101  :lol

D.

Mark Jones

Hi Don, yes that's much clearer now, thanks. Hope I can address your questions properly.

Structures are nothing more than groups of data elements that can be accessed in the nested form you quoted, i.e. (lpRDMS.something). A structure is really just a virtual collection of offsets... when you say MOV [lpRDMS.ReparseTag],eax - the [lpRDMS.ReparseTag] is simply a memory offset where 4 bytes of memory was reserved by the assembler, as per the structure definition ReparseTag DD ?. It's almost the same thing as making a whole bunch of individual NAME.FUNC db x DUP(?) statements. Here are the structures you are interested in for reference, from \masm32\include\windows.inc:


REPARSE_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    union
        struct SymbolicLinkReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct MountPointReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct GenericReparseBuffer
            DataBuffer db ?
        ends

    ends
REPARSE_DATA_BUFFER ENDS

REPARSE_GUID_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    ReparseGuid GUID        <>
    struct GenericReparseBuffer
        DataBuffer db ?
    ends

REPARSE_GUID_DATA_BUFFER ENDS


I tried to test your code and ML.exe complained of the DD's in the lpRDBMS and lpRDBgui definitions and in the syntax of myBuffer. Was this what you meant?


.data?
    myBuffer    db (20*1024) dup(?)
    lpRDBms     REPARSE_DATA_BUFFER<>
    lpRDBgui    REPARSE_GUID_DATA_BUFFER<>


You'll want to define these in the DATA? section because of the size of the buffers - if they were declared in the .DATA section then your executable would increase by at least 20kb because .DATA is read from the file, whereas .DATA? elements are created (blank) in ram at runtime.

I am confused myself about the topography of these structures. I am not familiar with these functions. :lol The structures contain a lot of word-size elements however, which are typically NOT memory pointers. A memory pointer is usually DWORD in size, because the full 4GB "flat" memory model needs 4 bytes to address it all. If there were an element in these structures which sounded like a buffer pointer and was DWORD in size and was designed to do this, you could get the address of "myBuffer" then put that value into the offset pointed to by the structure's buffer element, like so:


    lea eax,myBuffer
    mov dword ptr [lpRDBms.ReparseTag],eax


This of course assumes that the structure is used in this manner. LEA == load effective address, the offset of "myBuffer" becomes eax. "mov dword ptr [lpRDBms.ReparseTag],eax" means "convert this term into an offset and store eax there." But I'm not seeing a way to do this because those structures don't contain a valid DWORD buffer pointer element. Perhaps what MSDN is talking about is this:


        struct GenericReparseBuffer
            DataBuffer db ?
        ends


In \masm32\include\windows.inc these elements are defined as a single byte. Maybe what you want is this:


myREPARSE_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    union
        struct SymbolicLinkReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct MountPointReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct GenericReparseBuffer
            DataBuffer db (20*1024) dup(?)
        ends

    ends
myREPARSE_DATA_BUFFER ENDS

myREPARSE_GUID_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    ReparseGuid GUID        <>
    struct GenericReparseBuffer
        DataBuffer db (20*1024) dup(?)
    ends

myREPARSE_GUID_DATA_BUFFER ENDS

.data?
lpRDBms     myREPARSE_DATA_BUFFER<>
lpRDBgui    myREPARSE_GUID_DATA_BUFFER<>


Then you could access those data buffers like so:


; puts 4 bytes into the memory buffer space defined:
    mov dword ptr[lpRDBms.GenericReparseBuffer.DataBuffer],"!EYB"

; pop up a messagebox with the word "BYE!" in it:
    invoke MessageBox,0,offset [lpRDBms.GenericReparseBuffer.DataBuffer],0,MB_OK


Again I'm not sure if this is how windows intended these structures to function but now hopefully you have some new things to try. :bg

Regards,
Mark
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Don

Hi Mark, I'm glad I'm not thie only one confused by these c things  :wink

Don

I'm off to me bed. I know how to do this in Delphi; but I'll be buggered if I'll give up on asm now. Speak to you all in the morning - with a clearer head and a sharper pencil.

D.

donkey

Quote from: Don on February 24, 2006, 10:32:46 PM
Hi Edgar,

Is there no way that I can make the structure point directly to the buffer?

no eax, no nothing -  can I point lpRDBms and lpRDBgui directly at the first byte of rbuffer and use whichever structure I prefer?

Sorry if this seems dense but I did ask for pointer 101  :lol

D.

Hi Don,

I am sorry but I don't quite understand what you are asking here, the method I demonstrated is the most efficient way to address the problem and works quite well. I cannot see any point in having one buffer pointing to another if that's what you are trying to do. First off it only obfuscates the code and second I can think of no practical way of doing it other than using a UNION, for example...

REPARSE_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    union
        struct SymbolicLinkReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct MountPointReparseBuffer
            SubstituteNameOffset dw ?
            SubstituteNameLength dw ?
            PrintNameOffset dw      ?
            PrintNameLength dw      ?
            PathBuffer dw           ?
        ends
        struct GenericReparseBuffer
            DataBuffer db ?
        ends
    ends
REPARSE_DATA_BUFFER ENDS

REPARSE_GUID_DATA_BUFFER STRUCT
    ReparseTag dd           ?
    ReparseDataLength dw    ?
    Reserved dw             ?
    ReparseGuid GUID        <>
    struct GenericReparseBuffer
        DataBuffer db ?
    ends
REPARSE_GUID_DATA_BUFFER ENDS

REPARSE_STRUCT STRUCT
UNION
lpRDBgui REPARSE_GUID_DATA_BUFFER <>
lpRDBms REPARSE_DATA_BUFFER <>
ENDS
REPARSE_STRUCT ENDS


Then declaring your structure as follows...

.data?
MyBuffer REPARSE_STRUCT <>


You would then address it as follows...

mov eax,[MyBuffer.lpRDBgui.ReparseGuid]
mov eax,[MyBuffer.lpRDBms.SymbolicLinkReparseBuffer.SubstituteNameOffset]


As for Delphi you will most likely find that it uses the method I originally posted when compiled. At any rate I don't quite see what you are asking for so I will bow out of this thread.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable