With the use of the MASM high level syntax "invoke", Windows API code can be written very much like compiler based languages like "C" or "Pascal", the only real difference is that you have to pick up the return value as a separate line.
LOCAL ReturnValue :DWORD
invoke
FunctionName, par1,par2,par3,par4
mov ReturnValue,
eax
This is in place of the less readable form,
push par4
push
par3
push
par2
push
par1
call
FunctionName
mov
ReturnValue, eax
There is a considerable advantage in terms of code reliability by using the "invoke" syntax in that function calls are type checked against the function prototypes in the include files which catches parameter mismatches.
There are some situations where manual stack pushes and function calls are useful but unless you enjoy the extra typing and assembly error that follow from the lack of type checking, there is advantage in terms of both coding speed and reliability by automating the API function calls. This is particularly evident when coding message loops with nested conditional testing.
For any that need to be convinced, there is a directory in the example code called "oldstyle" which shows how slow and error prone the full manual technique is and it only builds at the same size as the generic template that uses the MASM pseudo high level syntax.
The high level [.if -- .endif] syntax allows a reasonable simulation of the C "switch" block or Basic's "Select Case" syntax which can be nested in the normal manner and it is here where high level type clear coding has its real advantage.
.if var
== 1
; conditional code
.elseif
var == 2
; conditional code
.else
; default code
.endif
The traditional [cmp eax, value -- je label] produces nightmares in the same situation.
The use of the high level simulation in MASM improves the code throughput of "hack" Windows API coding so that the more difficult areas of loop optimisation and other performance related issues can be addressed within a reasonable timeframe.
When you use MASM's pseudo high level syntax, you are taking advantage of MASM's "macro assembler" capacity, you code does not become bloated or compromised in the same way that compilers are. This capacity can be extended by writing "macros" that further automate common forms of coding.
The following small macros from MASM32 demonstrates this,
return MACRO arg
mov eax, arg
ret
ENDM
allows the programmer to exit the message proc by using the familiar "C",
return 0
which is expanded by the assembler into,
mov eax,
0
ret
Another macro used is,
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
which allows text to be directly embedded into the code.
szText Msg1,"This is a zero terminated string"
invoke MessageBox,hWin,ADDR Msg1,ADDR szDisplayName,MB_OK
This allows far more intuitive coding than having to go back to the initialised .data section using,
Msg1 db "This is a zero terminated string",0
Embedded data in the .code section has an advantage in that it normally is a lot harder to find and hack and it is normally not writable in the same way as the .data section. It is also an efficient way to use small amounts of data without needing to place it in the .data section.
For programmers who wish to keep the more intuitive placement of text near the code that uses it while placing the data in the .data section, there is an easy way to do just that, written inline with the source code,
.data
Msg1 db "This is data written in the .data section",0
.code
works fine. ML.EXE resolves the code and places the data in the .data section.
MASM32 has intentionally avoided using complex macros as they are not initially easy to understand but there is considerable power and speed of coding by understanding and using correctly written macros. The following is a slightly more complex macro that makes using a standard message box as easy as writing it in Visual Basic where you can use literally quoted text or direct addresses of zero terminated strings or combinations of both.
MsgBox hWnd,"Hi, I am written in MASM32","Greetings",MB_OK
This is the MACRO that produces the MsgBox command.
MsgBox MACRO handl, TxtMsg, TxtTitle, styl
LOCAL Msg1
LOCAL Titl
If @InStr(1,<TxtMsg>,<ADDR>) eq 0
If @InStr(1,<TxtTitle>,<ADDR>) eq 0
.data
Msg1 db TxtMsg,0
Titl db TxtTitle,0
.code
invoke MessageBox,handl,ADDR Msg1,ADDR Titl,styl
EXITM
EndIf
EndIf
If @InStr(1,<TxtMsg>,<ADDR>) gt 0
If @InStr(1,<TxtTitle>,<ADDR>) eq 0
.data
Titl db TxtTitle,0
.code
invoke MessageBox,handl,TxtMsg,ADDR Titl,styl
EXITM
EndIf
EndIf
If @InStr(1,<TxtMsg>,<ADDR>) eq 0
If @InStr(1,<TxtTitle>,<ADDR>) gt 0
.data
Msg1 db TxtMsg,0
.code
invoke MessageBox,handl,ADDR Msg1,TxtTitle,styl
EXITM
EndIf
EndIf
If @InStr(1,<TxtMsg>,<ADDR>) gt 0
If @InStr(1,<TxtTitle>,<ADDR>) gt 0
invoke MessageBox,handl,TxtMsg,TxtTitle,styl
EXITM
EndIf
EndIf
ENDM
MASM32 has been written without any compromise to the interests or format of other languages, it aims at maximising the advantages of writing in a true low level language. The format of the include files and the example code uses generic assembler data sizes in the form of BYTE, WORD, DWORD, QWORD. It does not attempt to implement abstract theories of classes or any other layering techniques but simply to make available the true low level power of the best available assembler.
The data sizes are directly related to the register sizes in the x86 series of processors where there is an exact correlation between data sizes and register sizes.
Register DATA size
al
= BYTE 8 bit
ax
= WORD 16 bit
eax
= DWORD 32 bit
mm(0)
= QWORD 64 bit
Compare this direct hardware based simplicity to the current situation in 32 bit Windows C++ which has over 60 different data types based around abstract class theory and where the names of different data types mean different things depending on which operating system version it is built on.
The WINDOWS.INC file has had all of the data types converted to generic
ASM data types to remove the added layer of complexity in the 60 or so
C++ data types that reduce down to the generic asm BYTE, WORD, DWORD, QWORD.
This removes one of the major error sources, incorrect data types. There
are a set of conversions in WINDOWS.INC for programmers who are porting
code written with C/C++ data types into MASM32.