Simple question on Iczelion's first example.
The code is following:

.Model Flat,StdCall
Option CaseMap:None
includelib kernel32.lib
includelib user32.lib

MsgBoxCaption db "Iczelion Tutorial No.2",0
MsgBoxText db "Win32 Assembly is Great!",0

invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK
invoke ExitProcess, 0
end start

Here we use addr to get the address of two defined strings. If we don't, the program can be assembled and run. But it will crash while running.

My question is: since invoke has the ability to check the type of parameters with prototype, why can't it find that MsgBoxText is a byte, not an 32 bit address?
Posted on 2004-09-22 06:34:26 by dislimit

What you need is te ADDRESS of the variable, not the variable itself. When you use ADDR in an invoke call, you are using the ADDRESS of the variable.

The distinction you have here is between the VALUE of a variable and WHERE it is located in memory. Where it is located is the ADDRESS of the variable.

To address your question, it appears that without ADDR being used, it defeats the type checking with the size of memory operands.

Here is the test piece that demonstrates this problem.

ExitProcess PROTO :DWORD

MessageBox equ <MessageBoxA>

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

; ?????????????????????????????????????????????????????????????????????????

ttl db "Title",0
msg db "Text Message",0

invoke MessageBox,0,ADDR msg,ADDR ttl,MB_OK
invoke ExitProcess, 0

end start

This will deliver an error if ADDR is used because an address in 32 bit Windows is always 32 bits in size. Remove the ADDR and it will build and crash on run. Note that the prototype is purposely written incorrectly with a BYTE value instead of a DWORD.


hutch at movsd dot com
Posted on 2004-09-22 06:39:38 by hutch--
Here is my understanding, please correct mistakes if any.

invoke MessageBox, NULL, MsgBoxText, addr MsgBoxCaption, MB_OK

When this wrong statement is assembled, masm automaticly convert the BYTE value of MsgBoxText into DWORD. But when we use a DWORD in a BYTE case, it can not be converted automaticly and thus provide the error notification.

Is the type checking ability of masm that weak?
Posted on 2004-09-22 07:35:21 by dislimit
some like yes.. but also pointers are not defined inside the language like they are in C, pheraphs are only defined at the end as dwords.. is a extrange way.... try follow but not follow...

EXample LPSTR is only a name for some like
typedef char* LPSTR;

and c can "convert" more like check if you are passing a pointer to a string..

I guess somewhere in the include files for masm....

define LPSTR DWORD ;dont know the sintaxis....

then is only checking inf you are passing a dword.. but not cant check the semantic if is a pointer, because pointers.. are not define like some diferent than a dword....
Posted on 2004-09-22 07:56:14 by rea
The weird thing is that MASM accepts BYTE data when the proc proto says it wants a DWORD. Then again, this is size expansion, the same kind of type promotion being done in C. And you can't go the other way, like specifying a DWORD to a proc taking a BYTE argument.

...this is why an assembler should either do no type conversion (but rather bitch you're doing something bad), or go all the way and distinguish between integers and pointers. I prefer the "no type conversion" way.
Posted on 2004-09-22 09:29:22 by f0dder
You may be finding the problem because a string is an ARRAY of BYTEs rather than a simple data type. The type checking in MASM is rudimentary, it counts parameters and where it can it tests data sizes but its not hard to fool the type checking in an assembler as the alternative would be strong typing which would make some assembler code very difficult to write.

You have overrides in C to get around it, in assembler you tend to get it the other way, minimal type checking.
Posted on 2004-09-22 09:47:02 by hutch--
MASM does the same thing for bytes as well as strings/arrays (string = array of bytes), and this is size extending it. And it even does it in a pretty lame way, when a single movzx+push would suffice :)

svar db "string"
bvar db 1

procd proc x:dword
mov eax, x
procd endp

invoke procd, svar
invoke procd, bvar


push 0
mov al, svar
movzx ax, al
push ax
call _procd@4 ; procd(x)
push 0
mov al, bvar
movzx ax, al
push ax
call _procd@4 ; procd(x)

...simple type promotion, just like in C. Cause of many a "duh!", since many people don't expect this from an assembler.
Posted on 2004-09-22 09:54:43 by f0dder