Page 1 of 1

MASM - Getting Started With MASM

#1 GunnerInc  Icon User is offline

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,281
  • 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:
cvtres
lib
link
link16 - 16bit linker
ml
ml614 - 16bit vertsion
rc

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) http://www.smorgasbordet.com/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
    .else
        ; neither, do something else
    .endif

    ; 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
Done:


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:
.data
szHello     BYTE    "HELLO", 0

.data?
lpszHello   byte    8 dup (?)

.code
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    
    Done:

    invoke  MessageBox, NULL, addr Hello, NULL, NULL
    invoke  MessageBox, NULL, offset lpszHello, NULL, NULL  
    ret
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

OFFSET -
    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? 3
  • +

Page 1 of 1