Hi.. im learning assembly it's been a few days. I'm confused at the moment about this "proc" stuff
I'm looking to do the following code but in masm (ofcourse :p )
function example(szString as string, StrSize as integer)
mov eax, szString
mov ecx, StrSize
end function
I know basic doesnt support assembly, but what im needing is an example of how to do such a task in masm using proc.. i've tried and failed :/
.386
.MODEL FLAT, C
.CODE
example PROC szString:PTR BYTE, StrSize:DWORD
mov eax, szString
mov ecx, StrSize
;..
ret
example ENDP
END
myfunc proc pStr:DWORD,iLen:DWORD
mov eax,pStr
mov ecx,iLen
ret
myfunc endp
The assembler doesn't really care much for types, only their sizes, so the result is that most things are just DWORDs.
When you want to pass a complex type (anything that won't fit into a dword) then you have to pass a pointer to it (its address; a reference) which is a dword (of course!)
Hutch has placed TYPEDEF's in windows.inc for most C type names - a few conflict with MASM reserved words, however
i think MASM is ok, so long as the type used in the PROTO is the same as the PROC and, as Tedd mentioned, the size is correct
UINT is TYPEDEF'ed, but i think INT is a conflict, so i use UINT for unsigned and DWORD for signed :P
LPCSTR and LPSTR are both TYPEDEF'ed
INCLUDE \masm32\include\masm32rt.inc
;#############################################################################
ConOut PROTO :LPSTR,:UINT
;#############################################################################
.DATA
szTestStr db 'Hello World',13,10
;#############################################################################
.CODE
;*****************************************************************************
_main PROC
INVOKE ConOut,offset szTestStr,sizeof szTestStr
INVOKE ExitProcess,0
_main ENDP
;*****************************************************************************
ConOut PROC lpStr:LPSTR,uLen:UINT
INVOKE GetStdHandle,STD_OUTPUT_HANDLE
push 0
mov edx,esp
INVOKE WriteFile,eax,lpStr,uLen,edx,NULL
pop eax
ret
ConOut ENDP
;#############################################################################
END _main
I prefer, like clive's code shows, to use PTR BYTE for a pointer to a string. It just makes it clearer that it's a pointer.
Likewise for any other type of pointer, for example PTR QWORD.
I know where the strong typing comes from but I also know the problems it generates, how and where do you find the SIZE of the data type. The C documentation contains another theory, that of portability across different OS versions where the basic word size varies depending on the hardware. Now this is fine if you are writing code that must be interpreted by a C compiler on different operating systems but for an assembler its a disaster in that an assembler needs to know the SIZE, not the NAME of a data type.
When you stick to the generic assembler types for a given hardware, x86 in this context you remove one of the great ambiguities that plagues programming in portable languages, an assembler pays the price of not being portable but gains in its lack of interpretation, in this 32 / 64 bit world you know the byte count of every data size the assembler supports and that makes the functions calls perfectly clear and unambiguous. You can write MASM 32 bit code so it looks like C but you pay the price of having to go look for how big it is, with generic data types you already know.
i must be lazy :bg
i just use the "sizeof" operator
i see a lot of code (and write some) that uses something like ADD EDI,4 :P
we all know it really means ADD EDI,sizeof DWORD or similar
i have been trying to use stronger type'ing in my definitions
it helps me verify my code against MS documentation
sometimes, it can help avoid bugs
i see "LPSTR" and i know i am passing a string pointer