Page 1 of 1

MASM - Getting Started With MASM

#1 GunnerInc   User is offline

  • "Hurry up and wait"
  • member icon

Reputation: 917
  • View blog
  • Posts: 2,358
  • Joined: 28-March 11

Posted 15 October 2011 - 06:05 PM


Getting Started with MASM

What is MASM?
MASM is a Macro Assembler from Microsoft (ml.exe). It has been around since the early 80's. It is a multi pass x86 assembler that produces COFF exes.

Where can I get it?
Microsoft does not sell MASM anymore, but ml does come with Visual Studio, Windows Driver Development Kit, Windows Software Development Kit. Along with ml, you will also need a linker and a few other files. I will not discuss getting the files from MS, since you will have to get and convert all the C header files and make sure you have the proper dlls. Instead I will discuss MASM32 - MASM32 contains:
link16 - 16bit linker
ml614 - 16bit vertsion

and a few more binaries. It also comes with an editor to edit your asm files, tons of examples with source, C header files converted for MASM, lib files, and the MASM32 library wich contains MANY usefull functions and source.

MASM32 also comes with poasm (macro assembler), polib (lib manager), and porc (rc to res converter) from Pelle Orinius (PellesC)

Pelles' tools seem to create optimized headers and smaller exes

Why MASM? When I chose Assembly MANY years ago, MASM had a large user base (read - support), tons of sample code and a prebuilt library of functions so I did not have to reinvent the wheel. Users of other Assemblers will say MASM is a HLL. Why, because of macros, invoke, if/while loops? BLAH, many of those Assemblers now have invoke and if/while loops.

There are 2 ways you can "call" functions - with invoke and with the mnuemonic call. Invoke is just a macro that makes sure the correct number of parameters are passed to the stack and also some type checking.

    push    NULL
    push    NULL
    push    offset szHello
    push    HWND_DESKTOP
    call    MessageBox

    invoke  MessageBox, HWND_DESKTOP, offset szHello, NULL, NULL

Both produce the same exact code

    ;if/endif block
    .if eax == 300
        ; do something for 300 here
    .elseif eax == 400
        ; do something for 400 here
        ; neither, do something else

    ; manual if/endif block
    cmp     eax, 300
    jne     @F
    ; do something for 300 here
    jmp     Done
    cmp     eax, 400 
    jne     @F
    ; do something for 400 here
    jmp     Done
    ; neither, do something else

The .if block creates the same code as the manual coded .if block above

In MASM, there are 2 important operators - ADDR and OFFSET
ADDR gets the address of a variable at runtime
OFFSET gets the address of a variable at link time

HUH?! Ok, let's explain with a little code:
szHello     BYTE    "HELLO", 0

lpszHello   byte    8 dup (?)

SomeProc proc
LOCAL   Hello[8]:BYTE    
    lea     esi, szHello
    lea     edi, Hello
    lea     ebx, lpszHello
    mov     byte ptr [edi], 0
    mov     byte ptr [ebx], 0
    mov     al, byte ptr [esi]
    inc     esi
    cmp     al, 0
    je      Done
    mov     byte ptr [edi], al
    mov     byte ptr [ebx], al
    inc     edi
    inc     ebx
    jmp     @B    

    invoke  MessageBox, NULL, addr Hello, NULL, NULL
    invoke  MessageBox, NULL, offset lpszHello, NULL, NULL  
SomeProc endp

At runtime, the address of the Hello buffer is not known, it's address is somewhere on the stack... Behind the scenes, ADDR will do
    lea     eax, Hello

so this:
     invoke  MessageBox, NULL, addr Hello, NULL, NULL

will get assembled as:

    push    NULL
    push    NULL
    lea     eax, Hello
    push    eax
    push    NULL
    call    MessageBox

ADDR uses eax to get addresses, remember that... You cannot use eax BEOFRE ADDR or you will get the error - A2133 register value overwritten by INVOKE

    mov     eax, 0
    invoke  MessageBox, eax, addr Hello, NULL, NULL

is incorrect as eax will be overwritten by ADDR

    invoke  MessageBox, NULL, offset lpszHello, NULL, NULL  

The address of lpszHello IS known at link time since it is in the .data? section. OFFSET returns its address offset from the base starting address of your exe.

You will see code using ADDR all the time. I am against that, you should be able to look at code and know if it is a local or global variable. I only use ADDR for local variables. OFFSET for anything in the .data, .data? sections and to get the address of a proc.

This post has been edited by GunnerInc: 17 October 2011 - 04:04 PM

Is This A Good Question/Topic? 5
  • +

Replies To: MASM - Getting Started With MASM

#2 kromag   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 16-July 16

Posted 19 July 2016 - 07:16 AM

Interesting collection you have here.
Thanks for taking the time to put all this information together.
Kromag Momag
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1