Masm32: What you absolutely need to get started
Installation of the libraries
Step 1: Download the Masm32 SDK from https://masm32.com/download.htm (you must ignore any Windows warnings)
Step 2: Open m32v11r.zip, and run install.exe - two minutes later, you will see a window Installation success
Step 3: You may or may not click "Yes" when the QEICON.VBS window pops up - decide yourself
Step 4: Close the small Installation is complete window (you may read the Intro.txt)
Step 5: You should install the MasmBasic package (all remarks in green below refer to this package, which is fully compatible with all Masm32 macros and libraries)
Step 6: As soon as you read in the upper right corner “... the usual disclaimers apply”, hit the F6 key
Step 7: If you see
a "Missing tool" box, click OK to install UAsm; a few seconds
later, see your first assembly program in action!
(If you don’t want to use RichMasm for some
reason, at least get UAsm.
Many of the new SSE+ instructions don’t work with the old MASM version 6.14
that comes with the Masm32 SDK. Newer versions of MASM exist, but some of them
are pretty buggy, and compared to UAsm they are awfully slow.)
Optional but highly recommended for serious work:
- After installing MasmBasic, google for Win32.hlp; it might be available at this Modula-2 page as Win32 API Help file (check also the Petzold book). Extract Win32.hlp to \Masm32\RichMasm\help\WIN32.HLP (this makes sure that context-sensitive F1 works in RichMasm)
- Get a debugger: Download OllyDbg and extract all files to \Masm32\OllyDbg\*.*. If you use MasmBasic's RichMasm editor, insert int 3 somewhere in your code, hit F6 and see the debugger in action; Olly is very simple, you will need only the F7 ... F9 keys
- In case you do not have MS Office, install the free Microsoft Word Viewer: It will speed up RichMasm by more than a factor 20.
Hello World in Masm32 (in case you are impatient)
This is a very simple skeleton for testing your installation. Assemble, link & run it (in RichMasm: by pressing F6), or insert your first mov eax, 123 somewhere between start: and exit
--------------------------------------------------------------------------------
include \Masm32\include\masm32rt.inc
.data
; initialised variables
MyAppName db "Masm32:", 0
MyReal8 REAL8 123.456
.data?
; non-initialised (i.e. zeroed) variables
MyDword dd ?
.code
start:
invoke MessageBox, 0, chr$("A box,
wow!"), addr MyAppName, MB_OK
mov eax, 123
; just an example – launch
OllyDbg to see it in action
exit
end start
--------------------------------------------------------------------------------
Help and tutorials, recommended reading
\Masm32\help\hlhelp.chm |
high level language in Masm: .if / .elseif / .endif, .Repeat ... .Until etc, a must read |
\Masm32\help\opcodes.chm |
how do instructions like mov, inc, add, sub etc work? |
\Masm32\RichMasm\help\WIN32.HLP |
if you saved it there, select e.g. "CreateWindowEx" in RichMasm and hit F1 |
\Masm32\MasmBasic\MbGuide.rtf |
open it from the RichMasm File menu, "Guide to MasmBasic" |
\Masm32\help\*.* |
if you find the time, study them all... |
\Masm32\help\masm32.chm |
the Masm32 library functions |
\Masm32\macros\macros.asm |
Masm32 macros |
\Masm32\include\masm32rt.inc |
read it to understand why include \Masm32\include\masm32rt.inc is enough |
\Masm32\examples |
sample code for all occasions |
use BASIC syntax (Open “I”, Print, Dim, Instr_, Dll, Declare, ...) in assembly |
|
essential guide to programming Windows |
|
|
registers, memory and addressing, instructions, calling conventions |
Randall
Hyde’s Art of Assembly |
one
of the few good books on assembly programming |
Daniel
Kusswurm’s Modern X86 Assembly… |
|
Masm Programmer’s Guide (search the web...) |
essential guide for programming in Masm |
Microsoft Macro Assembler Reference |
online documentation at MSDN; see also MASM history |
Tips, Tricks and Traps
The following is addressed to those who have experience in a high level language such as BASIC or C.
You are bound to stumble over some assembler oddities - read this section carefully.
- The "register gets trashed" trap:
Assembly beginners stumble inevitably over the phenomenon that registers "suddenly" change their values,
although there is apparently
no reason for such magic changes. Here is a short explanation why.
eax |
accumulator |
trashable, used e.g. for returning values |
ebx |
base |
general purpose protected register |
edx |
data |
general purpose trashable register |
esi |
source index |
general purpose protected register, used e.g. in lodsd, movsd |
edi |
destination index |
general purpose protected register, used e.g. in stosd, scasb |
ebp |
base pointer |
used for handling LOCAL variables - don't touch |
esp |
stack pointer |
used for push & pop and passing parameters - don't touch |
* protected register (ebx, esi, edi, ebp):
1. If you use one of these
registers, you must save it on entry into a proc, and restore it before
the ret
(you should avoid using ebp, as it is used for LOCAL variables; if
you use LOCALs, do not use ebp explicitly, and
do not save it)
2. an invoke GetTickCount or similar call of a Windows API will not change the protected register
* trashable register (eax, ecx, edx):
1. you can do whatever you want with this register
2. Windows will do whatever it wants with this register, so (most frequent noob error...!)
do not assume that e.g. ecx still has the same value after (for example) an invoke MessageBox, ...
3. macros of the print "Hello" type are calls to Windows APIs and will therefore trash these registers
Note that if you use only MasmBasic macros such as Open "O", #1, "MyFile.txt" or Print Str$("eax=%i", eax), the ecx register
will not be trashed; and you are not even obliged to save it.
For more detail, search Masm32 for ABI or see Register Preservation Convention in \Masm32\help\asmintro.chm
- The LOCAL variables trap: They will contain garbage, so you must
initialise them if you want zeroes:
MyTest proc
argText:DWORD, argTitle:DWORD
LOCAL LocVarA:DWORD, LocVarB, pt:POINT,
LocBuf[260]:BYTE
; ClearLocalVariables |
; in MasmBasic, you can clear all local variables with one instruction |
mov LocVarA, 0 |
; clear the first local variable |
and LocVarB, 0 |
; and .. 0 has the same effect but is three bytes shorter: 4 instead of 7 bytes |
and pt.x, 0 |
; and 0 clears the two DWORD |
and pt.y, 0 |
; members of the POINT structure |
mov LocBuf, 0 |
; a nullbyte delimits a string, so this "clears" the whole buffer |
invoke MessageBox, 0, argText, argTitle, MB_OK |
|
ret
MyTest endp
- The .if eax<0 trap:
This is
another trap for beginners...
mov eax, -1
.if eax<0
MsgBox 0, "Eax is less than
zero", "Hi", MB_OK
.else
MsgBox 0, "Surprise, surprise:
eax is NOT less than zero", "Hi", MB_OK
.endif
The reason is simple: Registers are by definition unsigned integers. After a mov eax, -1, the register contains the
value 0FFFFFFFFh, decimal 4294967295 - and that is indeed a number way above zero. To achieve what you want
with .if eax<0, use .if sdword ptr eax<0 - this ensures that the register will be interpreted as a signed integer.
In MasmBasic, you can use .if signed eax<0 - the keyword signed is a simple equate for sdword ptr.
- The Console app trap
You assemble, link and run
this code, and nothing happens:
include \Masm32\include\masm32rt.inc
.code
start:
inkey "Masm32 is so easy!"
invoke ExitProcess, 0
end start
You try again, and the assembler complains about "fatal error: access denied"...
The reason is that if applications use e.g. print or inkey, they need a console window. The linker provides this
console window if it finds /SUBSYSTEM:CONSOLE in the command line. In some IDEs, you therefore need to use
"Console assembly and link", otherwise the application hangs. Note RichMasm autodetects whether your app
needs console or Windows mode, so simply pressing F6 ensures you get the right subsystem.
- Are 16 bits enough?
No, not really. 16 bits under Windows are obsolete. Strangely enough, some beginners still come to the Forum with 16-bit code snippets. Only if you have a compelling and absolutely plausible excuse for avoiding modern 32-bit code, search the web for masm 16-bit linker, and then go straight to the Masm 16-bit sub-forum.
- Are 64 bits better?
Only if you are running big servers, or working with 20,000*25,000 pixel images. Jumping from 16 to 32 bits was a quantum leap, sure (remember that 640k limit?); but apart from a handful of niche cases, there is practically no gain from using 64-bit code. It is often slower, also because it occupies more space in the instruction and data caches.
- Last but not least: A few Rules for the Forum
* Use include \Masm32\include\masm32rt.inc, not include C:\Masm32\include\masm32rt.inc; many people have installed Masm32 on a different drive, and it's a real nuisance having to replace C: with D: to test a code snippet
* To allow others to test your code, do not use environment variables for your paths. Masm32 has a hard-coded path structure, for good reasons.
* Post your complete code. Some believe that older members are eager to construct the missing headers around your snippets, but this belief is FALSE
* Formulate precise questions, provide precise error messages and error lines. You will get quicker and better answers
* Have fun with Masm, and enjoy the friendly atmosphere at the Masm32 Forum!