I'm having trouble moving a block of memory
from a huge block (read from a file) to a smaller block.

The problem (I think) most likely lies in my lack of understanding
of the IMUL instruction...

The code causes an access error (0xc0000005) after the
first message box.

Anyway, here's the code:

; I need to copy the 8KB after ((16384*count)+16) bytes.
xor eax,eax
xor edx,edx
mov al,B
mov dx,16384
imul dx,ax
add dx,16
invoke MessageBoxA,0,"DARN 1",0,0
invoke RtlMoveMemory,(addr MEM),(addr file+dx),8192
invoke MessageBoxA,0,"BIGGER DARN",0,0

If anyone has any ideas, I'd appreciate it.

- Mike
Posted on 2003-09-16 19:51:29 by ASMMike
Ok fisrt off EAX and EDX are used for IMUL
EAX is the value to be Mul'd

and EAX and EDX are part of the return... so you cant use EDX as part of your IMUL

You should also always clear EDX before using IMUL

ALSO IMUL is for Signed Values..

you should be using MUL

like this.

xor edx,edx
xor ecx,ecx

mov al,B
mov cx,16384
imul cx
add ax,16
Posted on 2003-09-16 20:03:39 by devilsclaw
Why use 16bit registers in win32bit? Waste one byte for the prefix 66h.

Try replacing invoke RtlMoveMemory,(addr MEM),(addr file+dx),8192 with

mov eax, offset file
add eax, edx
invoke RtlMoveMemory,addr MEM,eax,8192

ASMMike is using the other variant of imul which is imul dest, src, src There is no need to clear edx before mul/imul. You only need to do that for div/idiv.
Posted on 2003-09-16 22:03:51 by roticv
sorry my fault
Posted on 2003-09-16 22:17:16 by devilsclaw

devilsclaw's comment is correct when you use the "imul" instruction with only one operand. When you use it with more than 1 operand, you must be aware of the following:
With the two- and three- operand forms, however, result is truncated to the length of the destination before it is stored in the destination register.

Because a 16-bit register is limited to a value of 65535, your B value must be less than 4. Otherwise, the DX register (mov dx,16384) will have an erroneous value after the multiplication. The result is NOT extended to EDX.

You could extend your range with the following code and then use the value of EDX:

xor edx,edx
mov dl,B
imul edx,16384

Posted on 2003-09-16 23:31:17 by Raymond
Anyway 16384 = 2^14


movzx eax, count
shl eax, 14
or eax, 16
add eax, offset file
invoke RtlMoveMemory,addr MEM,eax,8192
Posted on 2003-09-17 00:21:26 by roticv
isnt RtlMoveMemory a NT only thing.... i would figure any software a person would make unless for them selfs only would want there software backwards compatilbe
Posted on 2003-09-17 00:26:07 by devilsclaw
To clarify, no "CopyMemory" aka RtlMoveMemory is not a NT only API call.
Posted on 2003-09-17 01:54:43 by Snoopy2K
reason why i thought that is because the only place i have seen RTL is in the NTDLL sofar i checked the MSDN and it says nothing about what OS it requires also RtlMoveMemory and RtlCopyMemory are two diff api's running from wdm...

it also is only referenced to as kernel mode..
Posted on 2003-09-17 02:03:12 by devilsclaw
Thanks to everyone who replied.
roticv, should have thought of that, nice solution!

As it turned out, other than my multiply code being wrong,
I needed to pass a pointer to a pointer to the data to the API
(that's alot of "to the"s!).

Everything seems to work fine for now.

Thanks again to everybody,
- Mike
Posted on 2003-09-17 18:35:04 by ASMMike
regarding clearing edx, wouldn't you want to do that anyway with mul since it's
edx:eax * reg right? so unless one of the operands is larger than a dword...
Posted on 2003-09-17 21:06:04 by grv575

There is never any need to clear EDX before a mul or imul instruction.

The mul instruction (unsigned multiplication) is always used with only one operand which must be a register or a memory value. If the operand size is a byte, the value in AL is implicitly multiplied by it and the result goes to AX. If the operand size is a word, the value in AX is multiplied by it and the result goes to DX:AX. And if the operand is a dword, the value in EAX is multiplied by it and the result goes to EDX:EAX.

mul edx is thus a perfectly acceptable instruction.

When the imul instruction (signed multiplication) is used with only one operand, the result goes into the same registers as with the mul instruction above. When used with 2 or 3 operands, the 1st operand is always the only destination register; no other register is ever modified with the result. If that destination register is an 8-bit or 16-bit register, none of the other bits of the extended register are modified by the result either.

Posted on 2003-09-17 22:14:43 by Raymond