Saturday, 7 October 2017

Programming MASM32 with windows32 SDK apis.

It has been quite a time I had posted anything. Hope to add more to the blog from hereon.

Today I will post as very simple and basic assembly language program to get an understanding of the basics. The assembler that we will be using is MASM (The Microsoft Assembler), one can download the setup from this site. MASM32 is library that provides you with a rich set of functions to make the life easier while writing in assembly language.

While writing this, I assume that you have at-least heard that, there is something called as "Assembly Programming" and the intel x86 architecture.

Software Prerequisites

Visual Studio 2005 or above.
MASM32

Code

Lets not waste time, We will directly jump to the code. I will explain each line of code in detail,

.386
.model flat, stdcall
option casemap : none

extrn MessageBoxA@16 : PROC
extrn ExitProcess@4 : PROC

.data
    Info db "This is a message box.", 0
    MyTitle db "Assembly prog.", 0

.code
begin:
    mov eax, 0
    push eax
    lea ebx, MyTitle
    push ebx
    lea ebx, Info
    push ebx
    push eax
    call MessageBoxA@16

    mov eax, 0
    push eax
    call ExitProcess@4
end begin
.386
.model flat, stdcall
option casemap : none

The above 3 lines are called as assembler directives.

.386
is pretty self explanatory, it is to inform the assembler the the below code is for x86 architecture. Other processor architecture is x64 which is not considered in this blog.

.model flat, stdcall
This directives tells the assembler that the function x86 calling convention to be used is stdcall. The x86 calling convention or the x86 function calling convention, are the rules that need to be followed when the function is called.
stdcall, had the following rules:
The function parameters should be pushed on stack from right to left, e.g. for function void func(int a, int b, int c), we will push c, the push b and the push a onto the stack.
Stack is cleaned by the callee, i.e. all the params pushed by the caller are poped by the callee. Caller should not do it.
Function return values are stored in EAX registers.

option casemap : none
All the symbol names are case in-sensitive. i.e MyTitle is different from mytitle is different from Mytitle and so on...

extern MessageBox@16
extern ExitProcess@4
We will see this at the end of the code explanation.

.data
This directive is to inform the assembler that the code that follows is the data part of the code. All the initialized and un-intialized data can be declared under this section.

Info db "This is a message box.", 0
MyTitle db "Assembly prog.", 0
Here we have declare 2 variables in data section, this is the info to be displayed on the MessageBox. `Info` is the on the message box, `MyTitle` is the title of the message box.

.code
To inform the assembler, that the code section starts here.

begin:
end begin:
This makes the assembler understand all the code within `begin` and `end begin` are the part of the `begin` routine.

Now we will call the MessageBoxA function, if we look at the prototype on MSDN, we see that it needs 4 parameters, please refer msdn for details
int WINAPI MessageBox(
  _In_opt_ HWND    hWnd,
  _In_opt_ LPCTSTR lpText,
  _In_opt_ LPCTSTR lpCaption,
  _In_     UINT    uType
);
We push the parameters from right to left, first we push uType 
mov eax, 0
push eax
We push 0, for the uType parameter. 0 stands for MB_OK, this shows the OK button
 
lea ebx,MyTitle
push ebx
Now we push the title on the stack. But note here the full title string is not copied to the stack, but, `lea ebx, MyTitle`, loads the effective address of MyTitle into ebx register. Then this effective address is pushed onto the stack.

lea ebx, Info
push ebx
Now we push the address of the `Info` onto the stack.

push eax
This is the hWnd parameter, we pass 0, i.e effectively NULL.

call MessageBoxA@16
We call the function's ASCII variant (UNICODE variant is also available, MessageBoxW). The @16 part is called as function decoration. Why 16, because MessageBoxA has 4 parameters each of size 4, hence 16. This will become more when we call ExitProcess function.

The above snippet shows the message box on the screen. Now we exit the process.

mov eax, 0
push eax
ExitProcess@4
We push the param for the function ExitProcess(), the only parameter is the exit code, we pass exit code as 0, that we have stored in eax register.

Now what is this,
extrn MessageBoxA@16 : PROC
extrn ExitProcess@4 : PROC
 
This is to inform the assembler that these 2 procedures are not present in the current code, but are present in some other library, that will be resolved while linking.
Save the above code in a file name "msgbox.asm"

Compiling & Linking

We will compile the code into coff (Common Object File Format) and link the create an executable.
It will be convenient to store the masm/bin path in the environment variable.
Open the visual studio command prompt for x86, set the path for MASM,
set PATH=%PATH%;C:\masm\bin\
cd to_path_of_msgbox.asm

Then compile the code msgbox.asm
ml /c /coff msgbox.asm
If all is ok, this will create a msgbox.obj file.

link /SubSystem:Windows /DefaultLib:kernel32.lib /DefaultLib:user32.lib msgbox.obj
The above command will link the .obj file to create an executable.
/SubSystem: Windows tells the linker that the code contains some UI part. There other subsystems as well, eg. console

/DefaultLib: Links the kernel32 and user32 to create our executable.

Now go ahead and run the created msgbox.exe file.

Warning

Found it here, sarcasm...
"Not for the faint of heart. If MASM is beyond you, take up server side scripting."