Code Design

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.