We need to have the assembler help us as much as possible, so we don't have to work as hard! The first trick is to use the include directive, just as you did in C/C++ and Java (different directive, same affect!). You can include a number of files that you will need or you can use the following:
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
include \masm32\include\masm32rt.inc
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
| .Model | The only thing we will use is FLAT, because it gives us all 4GB of memory |
| .Stack | This is the amount of stack space you want to reserve. 1KB is the default |
| .Data | Actually, we can have .DATA, .DATA?, .CONST, .FARDATA, and .FARDATA? You can get away with using only the .DATA |
| .Code | This is your algoritm, in syntaxically correct assembly language instructions! |
You can have more than one .DATA and one .CODE segment. The linker will get it figured out for you.
(To use binary, use a 'b' after the number.)
Declaring data can be interesting. You must keep track of the constraints of your data, what is the minimium and maximum size, it is signed or unsigned, is it real or whole? There is no special way to designate that the variable is signed or unsigned. You, the programmer, must keep that straight! Also, today, the tendency is to make everything a double word, because it is actually faster. When we talk about type, what we really mean is how many bits in the data? If you try to put one size variable into another size container (memory or register), the assembler will flag it as an error.
For the time being, we are only going to talk about integer data. Real numbers come later.
| Size | Name1 | Name2 |
|---|---|---|
| 8-bit | BYTE | db |
| sbyte | ||
| 16-bit | WORD | dw |
| sword | ||
| 32-bit | DWORD | dd |
| sdword | ||
| 64-bit | QWORD | dq |
Notes:
I
When an instruction has two operands, they are in the format of:
If you want to put a copy of the data in the EAX register into the EBX, it is:
If I want to add the values in the EAX and EBX register together and store the results in EAX, it would be in the form of:
In some programs, there is a way to create what looks like one instruction that is really many instructions. These are called macros. We will be using ones that come with MASM32. In C and C++, you can create a macro with the "#define" directive.
At other times, we will be using library functions to do some of our work, especially input and output!
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
; Build this with the "Project" menu using
; "Console Assemble and Link"
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros
; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code ; Tell MASM where the code starts
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
start: ; The CODE entry point to the program
print chr$("Hey, this actually works.",13,10)
exit
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
end start ; Tell MASM where the program ends
; #########################################################################
.386
.model flat, stdcall
option casemap :none ; case sensitive
; #########################################################################
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
; #########################################################################
.code
start:
jmp @F
szDlgTitle db "Minimum MASM",0
szMsg db " --- Assembler Pure and Simple --- ",0
@@:
push MB_OK
push offset szDlgTitle
push offset szMsg
push 0
call MessageBox
push 0
call ExitProcess
; --------------------------------------------------------
; The following are the same function calls using MASM
; "invoke" syntax. It is clearer code, it is type checked
; against a function prototype and it is less error prone.
; --------------------------------------------------------
; invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_OK
; invoke ExitProcess,0
end start
@echo off if not exist rsrc.rc goto over1 \masm32\bin\rc /v rsrc.rc \masm32\bin\cvtres /machine:ix86 rsrc.res :over1 if exist "minimum.obj" del "minimum.obj" if exist "minimum.exe" del "minimum.exe" \masm32\bin\ml /c /coff "minimum.asm" if errorlevel 1 goto errasm if not exist rsrc.obj goto nores \masm32\bin\Link /SUBSYSTEM:WINDOWS "minimum.obj" rsrc.res if errorlevel 1 goto errlink dir "minimum.*" goto TheEnd :nores \masm32\bin\Link /SUBSYSTEM:WINDOWS "minimum.obj" if errorlevel 1 goto errlink dir "minimum.*" goto TheEnd :errlink echo _ echo Link error goto TheEnd :errasm echo _ echo Assembly Error goto TheEnd :TheEnd pause