Hi,
I'm new to this board, well as a poster at least (ok, posted 4 times before a long time ago). First off let me start by saying this is a really awesome board, and there's tons of good information to be found.

Now on to my problem. I've created a ListView and want to write a simple Proc to add columns to it, so I came up with this:



;=================================================
; Insert Column (ListView)
;=================================================
InsertColumn Proc colWidth:DWord, szColCaption:DWord, lvHandle:HANDLE
Local col:LV_COLUMN

Mov col.imask, LVCF_TEXT Or LVCF_WIDTH
Mov col.fmt, 0
Mov col.lx, colWidth
Mov col.pszText, szColCaption
Invoke lstrlen, szColCaption
Mov col.cchTextMax, Eax
Invoke SendMessage, lvHandle, LVM_INSERTCOLUMN, 0, Addr col
InsertColumn EndP


I just do an Invoke InsertColumn, 180, Addr Col1Caption, hListView, where Col1Caption is defined as Col1Caption DB "Column1", 0 and hListView is the Handle of the ListView.
The problem is that the compiler don't like these two lines for reasons beyond me:



Mov col.lx, colWidth
Mov col.pszText, szColCaption


The compiler gives me an error A2070: invalid instructions operand. I was under the impression that all members of the LV_COLUMN struct was of type DWord, have I got it all wrong? Anyways, all help would be greatly appreciated.

Best regards,
Anders Pettersson
Posted on 2004-06-14 08:49:11 by EvilElvis
You are correct that all members of the structure are DWORDs. The problem lies in a limitation of the x86 family of CPUs. There is no instruction in the x86 family that can move data from one memory address directly to another, you must use a register or the stack to perform the move operation. When you tried...

Mov col.lx, colWidth

Both col.lx and colWidth are memory locations and therefore the Invalid Operand error. You have two choices...

push colWidth
pop col.lx

or

mov eax,colWidth
mov col.lx,eax
Posted on 2004-06-14 08:56:46 by donkey
Wow, talk about a quick response. :) Ok, I did not know that, thanks alot donkey, works like a charm now. :)
Posted on 2004-06-14 09:00:37 by EvilElvis
Hehe, what about movsb, movsw and movsd?
Posted on 2004-06-14 09:30:38 by roticv

Hehe, what about movsb, movsw and movsd?


Yeah, I keep leaving those out. Better to avoid them like the plague anyway they are verrry slow as you well know :) If you think about it PUSH and POP also move directly from memory to memory but for starting out it is best not to worry about these things.
Posted on 2004-06-14 09:41:02 by donkey
Hutch's macro collection - macros.asm (which comes with the masm32 package) contains
the m2m macro:


; memory to memory assignment
; -- --------------------------
m2m MACRO M1, M2
push M2
pop M1
ENDM
Posted on 2004-06-14 11:58:08 by Vortex
Bah Macros :(

Push/Pop is rarely the best way to do it, if you have a register you are better off using that. IMHO this task is not well suited to a macro at all. Each individual case is too different for a canned function. But then I am the anti-macro guy :)
Posted on 2004-06-14 12:30:52 by donkey
Donkey,

I like macros. :) You can do a lot of things with them. At the end, using macros is a personal choice.
Posted on 2004-06-14 13:24:14 by Vortex
I use macros for tedious data entering tasks, but not for writing the code. The usage of macros makes it difficult to count the number of bytes used.
Posted on 2004-06-14 13:29:33 by Sephiroth3

Donkey,

I like macros. :) You can do a lot of things with them. At the end, using macros is a personal choice.


Yeah I know, it's lonely being the only anti-macro guy but we all have our personal crusades :grin:
Posted on 2004-06-14 13:30:00 by donkey
Sephiroth3,

Do you count the number of used bytes in all your programs?
Posted on 2004-06-14 13:34:43 by Vortex

Sephiroth3,

Do you count the number of used bytes in all your programs?


I used to always count for jumps and to check to see if I could use a relative offset. Though since Jeremy changed the error message in GoAsm to indicate how many bytes I missed by I do it less frequently now. After all even MASM does not always choose the optimal jump length for complex blocks of code, I think FASM has the best jump optimizer from what I hear.
Posted on 2004-06-14 13:38:15 by donkey
Hi Donkey,

This quick macro example counts bytes between two labels:


.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

bytes MACRO a1,a2
local temp
temp TEXTEQU %(OFFSET a2-OFFSET a1)
% echo Number of bytes : temp
ENDM

.code
start:
xor eax,eax ; dummy instructions
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax
xor eax,eax

mylabel:
invoke ExitProcess,0

bytes start,mylabel

END start



The result during assembly stage:
[code]
Number of bytes : 20
[/code]

I think this macro can be helpfull to determine optimized jumps.
Posted on 2004-06-14 13:59:20 by Vortex
Well, usually I end up counting the bytes manually when I want to program some operation and I'm not sure of what would be the smallest approach. I don't bother to assemble it just to check, since it's usually much less than a screenful of instructions. Code is moved around when possible to reduce the number of full size jumps, but I never count the bytes to check whether a short jump is possible, it's quicker to just guess and change the jump later if it becomes too big.
Posted on 2004-06-14 14:20:11 by Sephiroth3

I don't bother to assemble it just to check, since it's usually much less than a screenful of instructions.


What do you do if you have houndreds of instructions? Count them one by one?
Posted on 2004-06-14 14:28:18 by Vortex
Hi Vortex,

Thanks I use GoAsm not MASM. But if you check my debug library I already have a macro to do this, I don't mind macros as long as, like Sephiroth3, they are not used in release code. For checking things with the debug library I am OK with them, but those are never included in any release.

Measure	=		mov [dbgmeasure],$+20 \

mov D[dbgmeasureline],@line+1

EndMeasure = pushad \
pushfd \
cld \
push @line-1 \
push [dbgmeasureline] \
push $-14 \
push [dbgmeasure] \
call DEBUGLIB:DbgEndMeasure \
popfd \
popad


DbgEndMeasure FRAME StartPos,EndPos,StartLine,EndLine

LOCAL dwBytes :D
LOCAL pMem :D

mov eax,[EndPos]
sub eax,[StartPos]
mov [dwBytes],eax
invoke GlobalAlloc,040h,80
mov [pMem],eax
invoke wsprintfA,[pMem],OFFSET DbgMeasureFmt,[dwBytes],[StartLine],[EndLine]
add esp,20
invoke DbgDebugPrint,[pMem]
invoke GlobalFree,[pMem]

RET
ENDF


Measure
movzx ecx,B
EndMeasure

Measured 7 bytes from line 338 to line 338
Posted on 2004-06-14 14:34:13 by donkey
Na... macros are the best. They are definitely your friend if you will let them... I see no point at all going through and removing macros for release builds. Thats alot of extra work that really doesnt need to happen. If your truely worried, design your macros with a common build switch...

All the OOP achitectures being designed all rely on macros. With out them it would be far to time consuming and teedious to achieve at an ASM level. As well in the case of COM they allow for standardization between varying COM architectures (Japteth's COMView generates typelib includes that use a standard macro name "STDMETHOD" before typelib data. This allows the end user to use either Japheth's method of COM calling, or redefine their own implementation of STDMETHOD to work with what ever architecture is confortable to them. In either case the include will work universally).

There is many good uses for macros... I just want to point this out...

Regards,
:NaN:
Posted on 2004-06-14 16:25:04 by NaN