News:

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

Multiple dereferencing

Started by King Nak, April 22, 2007, 06:07:39 PM

Previous topic - Next topic

King Nak

Hi all!

I'm quite new to assembler and I'm learning it right now by doing a little project.
I came to a point where I tried to access a specific index in an array contained in a struct.
The result was a quite complex line, but supprisingly to me, it worked!
Here's some code:

S_DATA STRUCT
curDat BYTE 100h DUP(?)
curLen WORD 0
S_DATA  ENDS

;; .....

ASSUME ebx:PTR S_DATA
lea eax, [ebx].curDat
mov byte ptr [eax[[ebx].curLen]], dl

This last line does a lot of things, and I'm wondering if it is assebled to
multiple instructions, or if it can be executed as it is.
and if so, what about performance?
I tried to do it another way, like this:

ASSUME ebx:PTR S_DATA
lea eax, [ebx].curDat
xor ecx, ecx
mov edx, [ebx].curLen
add eax, ecx
mov byte ptr [eax], dl

This version does the same, but is much longer and uses an extra register...
(I can't just say add eax, [ebx].curLen, because curLen is a WORD...)

What version would you prefer? Or should I simpely declare curLen as DWORD?

bye
King Nak

Tedd

In general, you only get one 'move' per instruction, so the first version doesn't work quite how it looks (and it doesn't get assembled to multiple instructions.)

mov byte ptr [eax[[ebx].curLen]], dl
..actually works as..
mov byte ptr [ebx + eax + OFFSET S_DATA.curLen], dl

and I'm afraid the second version isn't quite right either :(
- you're getting curLen into edx, then adding ecx (silly typo?)
- also, you're getting curLen as a dword into edx, rather than a word into dx

ASSUME ebx:PTR S_DATA
lea eax, [ebx].curDat
xor ecx, ecx
mov cx, [ebx].curLen
add eax, ecx
mov byte ptr [eax], dl

(..fixed)

which could easily be shortened to..
ASSUME ebx:PTR S_DATA
lea eax, [ebx].curDat
movzx ecx, [ebx].curLen       ;automagically sets the upper bits of ecx to zero
mov byte ptr [eax+ecx], dl


But unless you're particularly short on space (2 bytes?!) then you may as well make curLen a dword (as they're 'native' in 32-bit code.)
No snowflake in an avalanche feels responsible.

King Nak

Thanks for the answer...
I also just figured out that the first version doesn't work.

I didn't know movzx so far... quite useful. As I said, I'm very new to assembler,
and I know only a few operations.

I checked the MASM programmer's guide meanwhile
(here http://doc.ddart.net/asm/Microsoft_MASM_Programmers_Guide_v6.1/Chap_04.htm)
and found something in chapter 4 about changing the type of simple variables
using PTR. could this be used here somehow? For example like this
(I know this won't work...)

ASSUME ebx:PTR LZW_DATA
lea eax, [ebx].lzw_curDat
add eax, DWORD PTR [ebx].lzw_curLen
inc [ebx].lzw_curLen


bye
King Nak

dsouza123

In reference to the original post with the curLen DWORD ? modification.


    ASSUME ebx:PTR S_DATA

    mov eax, [ebx].curLen                  ; two lines are equivalent (the first is better in case of struct modification)
    mov eax, dword ptr [ebx+100h]

    mov byte ptr [[ebx].curDat[eax]], dl   ; three lines are equivalent (the first two are less error prone ie struct modification)
    mov byte ptr [[ebx].curDat+eax ], dl
    mov byte ptr [ebx+eax],dl


so here is a compact working version of the original

    ASSUME ebx:PTR S_DATA
    mov eax, [ebx].curLen                  ; get the index into the byte array
    mov byte ptr [[ebx].curDat[eax]], dl   ; put the value of dl in it


and for good measure

    inc byte ptr [[ebx].curDat[eax]]      ; increase indexed byte by one

    add byte ptr [[ebx].curDat[eax]], 10  ; increase indexed byte by ten


DON'T USE, here is an even more compact NON working version of the original, assembles but doesn't work

    ASSUME ebx:PTR S_DATA
    mov byte ptr [[ebx].curDat[[ebx].curLen]], dl   ; this version only uses ebx  (puts the value of dl into the indexed byte)

MichaelW

And don't forget the form that requires no ASSUME:

mov eax, [ebx].S_DATA.curLen
mov byte ptr [[ebx].S_DATA.curDat[eax]], dl

Which assembles to:

00401001 8B8300010000           mov     eax,[ebx+100h]
00401007 881418                 mov     [eax+ebx],dl

The same as:

ASSUME ebx:PTR S_DATA
mov eax, [ebx].curLen                  ; get the index into the byte array
mov byte ptr [[ebx].curDat[eax]], dl   ; put the value of dl in it

eschew obfuscation

ic2

It just so happen that i was trying to remove the assume directive about a week ago and gave up.  I know how to do it in other parts of my code using this:

MOV  EDX, IMAGE_EXPORT_DIRECTORY.AddressOfFunctions[edx]

but not under WM_NOTIFY everything i try don't work.

Don't mean to jump in but this is right up my ally...  Would you show me how to do this from the code style below ? .... Thanks in advance...

      .elseif wmsg == 4Eh    ;  WM_NOTIFY

           push    edx
           mov     edx, lParam

assume edx:ptr NMHDR

cmp [edx].code,  NM_CUSTOMDRAW



MichaelW

These all assemble without error, and correctly AFAICT.

    mov eax, [edx.NMHDR].hwndFrom
   
;00401000 8B02                   mov     eax,[edx]
   
    mov eax, [edx].NMHDR.hwndFrom

;00401002 8B02                   mov     eax,[edx]
   
    cmp [edx].NMHDR.code, NM_CUSTOMDRAW

;00401004 837A08F4               cmp     dword ptr [edx+8],0FFFFFFF4h

eschew obfuscation

ic2

I see.  I keep up a mistake to this day.  I was using

mov eax, [edx].NMHDR.hwndFrom

from the start before changing things... BUT with this next line

cmp [edx].code, NM_CUSTOMDRAW

no NMHDR.code How blind could i be...

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

i can use just line one or line two with line three and work.

Or i can use all three lines and it still works...


Thanks MichaelW