Hi,
Can somebody explain me how to move the memory adress I allocated with HeapAlloc in a DWORD var?
I tried this:
.data?
cdi DWORD ?
.
.
.
invoke HeapAlloc, heap, HEAP_ZERO_MEMORY, sizeof COPY_DIRECTORY_INFO
mov cdi, eax
mov [cdi].COPY_DIRECTORY_INFO.src[0], bl
I wondered why this produced errors at runtime, after debugging I saw masm produced something like this
mov dword ptr [cdi], eax
instead of
mov cdi, eax
Does this write the value in eax to the address in cdi?
Hi,
I have similar behavior with a procedure I wrote, so I'm interested either to know why MASM is not building exactly what we write.
In my case, it's no big deal because instead of jnge it is changed by jl and jnl by jge.
But the fact is, once compiled, we don't have exactly what we wrote. :tdown
Hi rev, that behavior is by design. "cdi" is defined as a DWORD, so MASM assumes it is a dword-sized variable. MOV cdi,eax is interpreted as MOV offset of variable,eax. This is correct, since you want to store a dword-sized value (the handle of the memory allocated) into 4 bytes of reserved memory. I have no idea what you are trying to do with bl and the array, however. :U
Also, try researching the ASSUME directive, this might help.
Thank you Mark for your answer,
I want cdi to be treated as this structure:
COPY_DIRECTORY_INFO struct
src db MAX_PATH dup (?)
dst db MAX_PATH dup (?)
COPY_DIRECTORY_INFO EndS
After memory allocation I copied the memory handle in eax to cdi and tried to fill the src member of the structure.
mov [cdi].COPY_DIRECTORY_INFO.src[0], bl
mov [cdi].COPY_DIRECTORY_INFO.src[1], 58
mov [cdi].COPY_DIRECTORY_INFO.src[2], 92
mov [cdi].COPY_DIRECTORY_INFO.src[3], 42
mov [cdi].COPY_DIRECTORY_INFO.src[4], 46
mov [cdi].COPY_DIRECTORY_INFO.src[5], 42
mov [cdi].COPY_DIRECTORY_INFO.src[6], 0
mov [cdi].COPY_DIRECTORY_INFO.src[7], 0
However, I get some strange behaviour in my application after these lines of code, some values of other vars, I never touched, seem to be modified.
OllyDbg gave me these lines:
0040147E . A1 A4314000 MOV EAX,DWORD PTR DS:[cdi]
00401483 . 881D A8314000 MOV BYTE PTR DS:[temp],BL <-- temp??
00401489 . C605 A9314000 >MOV BYTE PTR DS:[4031A9],3A
00401490 . C605 AA314000 >MOV BYTE PTR DS:[4031AA],5C
00401497 . C605 AB314000 >MOV BYTE PTR DS:[4031AB],2A
0040149E . C605 AC314000 >MOV BYTE PTR DS:[regbuf],2E <-- I never used regbuf here
004014A5 . C605 AD314000 >MOV BYTE PTR DS:[4031AD],2A
004014AC . C605 AE314000 >MOV BYTE PTR DS:[4031AE],0
004014B3 . C605 AF314000 >MOV BYTE PTR DS:[4031AF],0
I don't know what I am doing wrong, maybe something really basic. All I want is to copy the memory handle to cdi and use cdi to access the memory.
Edit: Well I get it to work if I take a register instead of cdi. But can someone explain me why this is not possible with vars? And I thought the brackets [] only dereferences a pointer, but when accessing a variable the brackets are also used?
Quote from: rev on August 02, 2006, 11:27:02 PM
Well I get it to work if I take a register instead of cdi. But can someone explain me why this is not possible with vars? And I thought the brackets [] only dereferences a pointer, but when accessing a variable the brackets are also used?
There's been plenty of discussion on this.
The Intel architecture generally only allows one level of deferencing at a time. This means that you can't access the memory pointed to by the memory pointed to by a register in one go, you need to do each step.
When defining symbols in MASM, the square brackets are implied for variables. In many assemblers this is not the case and the label is treated as the address of the value rather than the value. MASM assumes that you're more interested in the value and puts them in (including OFFSET/ADDR to 'remove' them).
This means that when you put brackets around a variable (not a register), it's actually the second set of brackets. Since the x86 can't do multiple levels of indirection, this doesn't make sense. The decision was made that the extra brackets should just be ignored (Hutch loves giving examples of code with 20 sets of brackets :eek but it still works exactly the same) as opposed to giving an error.
Basically, if you want to use a value as a pointer, it needs to be in a register.
Cheers,
Zooba :U
Here is a quick example of reference up and down.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.data
item dd 12345678
.code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
call main
inkey
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
main proc
LOCAL ptr1 :DWORD
LOCAL ptr2 :DWORD
; ---------
; reference
; ---------
mov ptr1, OFFSET item ; 1 write OFFSET to a pointer
lea eax, ptr1 ; 2 get effective address of pointer
mov ptr2, eax ; 3 store it in another pointer
; -----------
; dereference
; -----------
mov eax, ptr2 ; load pointer into register
mov eax, [eax] ; dereference it once
mov eax, [eax] ; dereference it again
print str$(eax),13,10 ; print the original data to the console
ret
main endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Thank you for your detailed answers, thats what I was looking for.