Masm32: What you absolutely must know to get started

Installation of the libraries

Step 1: Download the Masm32 SDK from

Step 2: Open, 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

Step 4: Close the small Installation is complete window

Step 5: You should read the text in the Intro.txt window

Step 6: You may install the MasmBasic package from

(all remarks in green below refer to this package, which is fully compatible with all Masm32 macros and libraries)

Step 7: After installing MasmBasic, google for Win32.hlp; it might be available at the PowerBasic tools page as Windows 32-bit API Help File.

Step 8: Install Win32.hlp and move it to \masm32\RichMasm\help\WIN32.HLP (this makes sure that F1 works in RichMasm)

Step 9: Install JWasm; all you need is the executable, i.e. Jwasm.exe; rename \masm32\bin\ml.exe to ml614.exe, then move Jwasm.exe to \masm32\bin and rename it to ml.exe (no need to rename the executables if you use RichMasm – it will automatically pick Jwasm if it finds ML 6.14)

Step 10: Run \masm32\richmasm\richmasm.exe, and click on one of the links under Masm32 examples; press F6, and see your first Masm32 application in action. Congratulations ;-)

Optional but highly recommended for serious work:

Step 11: Go to, pick the latest version (probably version 2), download and save as \masm32\OllyDbg\OllyDbg.EXE. If you use MasmBasic's RichMasm editor, insert int 3 somewhere in your code, hit F6 and see Olly in action...

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\

.data ; initialised variables

MyAppName db "Masm32:", 0

MyReal8 REAL8 123.456

.data? ; non-initialised (i.e. zeroed) variables

MyDword dd ?



  invoke MessageBox, 0, chr$("A box, wow!"), addr MyAppName, MB_OK

  mov eax, 123  ; just an example – launch OllyDbg to see it in action


end start


Help and tutorials, recommended reading


a must read


very useful, too


how do mov, inc, add, sub etc work?


these macros will make your coding easier


if you saved it there, it will open in RichMasm with F1


MasmBasic help file, opens in RichMasm with F1


if you find the time, study them all


Helps to understand why include \masm32\include\ is enough


sample code for all occasions

University of Virginia x86 Assembly Guide

Registers, Memory and Addressing, Instructions, Calling Conventions

Randall Hyde’s Art of Assembly

One of the few good books on assembly programming

Masm Programmer’s Guide (search the web...)

Essential guide for programming in Masm

Microsoft Macro Assembler Reference

Online documentation at MSDN

The Iczelion Tutorials

Essential guide to programming Windows

MasmBasic Quick Reference

Use BASIC syntax (Open “I”, Print, Dim, Instr_, Dll, Declare, ...) in assembly

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.



trashable, used e.g. for returning values



general purpose protected register



general purpose trashable register (but protected in MasmBasic macros)



general purpose trashable register


source index

general purpose protected register, used e.g. in lodsd, movsd


destination index

general purpose protected register, used e.g. in stosd, scasb


base pointer

used for handling LOCAL variables - don't touch


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



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


    MsgBox 0, "Surprise, surprise: eax is NOT less than zero", "Hi", MB_OK


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\



   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.

- Last but not least: A few Rules for the Forum

* Use include \masm32\include\, not include C:\masm32\include\; many 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 the 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 in the Masm32 Forum!