Inferno Web Development
  • Home
  • Forums
  • About
  • Links
  • Contact

Tutorials List

  • C++ Tutorials

Articles

  • Java
  • PHP
  • Photoshop
  • C#
  • C++ Qt GUI
  • C++ Win32 API
  • C++
  • MASM32
  • General News
  • JavaScript
  • Web Development
  • Windows Tweaks

Popular Tutorials

All time:

  • Website Header with 3D Fold Up / Lift Effect
  • C++ Win32 API Tutorial
  • Perfect C++ String Explode Split
  • Simple C++ DLL Loading a Message Box
  • Simple C++ Pointers and References

Programming Tutorials

Home

Introduction to MASM32

Submitted by Baran Ornarli on Mon, 08/18/2008 - 03:24.
  • MASM32

Table of Contents

  1. Getting Started
  2. Comments
  3. Basic Commands
  4. First Windows Program
  5. Your WinMain function
  6. Shutting Off a Win32 Process
  7. Basic Task Manager Processes
  8. Windows Process Handling

ASM is machine language that your computer reads with all computer programs. Every program that is compiled from any language such as C++ or Delphi is then converted to PC ASM through your compiler. PC ASM is what your CPU reads and it is quite difficult to read; however, with MASM32 you can code ASM in a similar fashion to C++ but without the complexity and hassle of PC ASM that your processor reads.

In ASM the PC has registers which are segments of memory that your CPU uses to handle memory. There is also stack data, and of course hard disk and RAM memory. The advantage of ASM is that it can work directly with memory and is considered the fastest type of code as long as it is coded correctly. By contrast, it also makes it a very difficult language, but we will try and simplify the process in this MASM32 Tutorial.

We won't delve into too much detail about MASM's internal workings and how ASM is interpreted by the computer, because the complexity can confuse many people. The basic understanding is that ASM commands are converted into simple electronic signals by your CPU that handle memory.

Getting Started

If you want to try out the examples in this tutorial, I recommend downloading RadAsm from http://www.radasm.com/ . Download the IDE pack, install it, and then download the Programming pack and install that too. Before you try and compile download the MASM32 compiler at the top of the page. Install MASM32 compiler, and then adjust your RadAsm settings so that RadAsm knows the locations of the MASM32 directories.

Here's the basic skeleton of a MASM program:
Skeleton:

.386
.model flat,stdcall 
option casemap:none
// the model of your program will usually be flat, stdcall
// There is stdcall syntax and C syntax of summoning functions
// the stdcall syntax means you call your program arguments from 
// RIGHT to LEFT rather than LEFT to RIGHT which is the C syntax.
.data
// This is your initialized variables that you will use.
// The format is: NameOfVariable db "Message",0
// the comma 0 is the null terminator indicating end of the message.
.data?
// This is your uninitialized variables that you will use.
.const
// Constant variables example: BUFFER_SIZE    equ 1024
.code
 start:
// Your code and everything goes in here.
 end start

The Registers:
eax -> This is the standard register that you will mostly be using.
ecx -> This is a counter register which is used in loops.

Comments

  ; The semicolon ; indicates a comment (to the right), which is // in C++ or other languages.

Basic Commands

  mov [destination],[source]
  ; This is a copy function, it copies from:
  ; Either memory to register
  ; register to memory
  ; register to register
  ; IT CANNOT COPY FROM MEMORY TO MEMORY. so don't try mov hInst, hInst2
  ; because they are both variables.
  ; example: mov eax,hInst ;copies the value of hInst to the register eax.
  invoke [function][arguments,] 
  ; Calls a function with arguments
  call [function]
  ; calls a function you have to push the arguments beforehand.
  push [object]
  ; This pushes/adds the object into the stack
  pop [object]
  ; This pops the object from the stack
  inc [register]
  ; increments register
  dec [register]
  ; decrements register
  add [register]
 Two ways to call a function:
   Standard Old way: 
     push MB_OK
     push offset ClassName
     push offset AppName
     push 0
     call MessageBox
     ; This is a C syntax call from Right to Left. 
     ; Reverse the order to work with stdcall.
     ; But this is messy and not a great method.
   New Way:
     invoke MessageBox,0,offset ClassName,offset Appname,MB_OK
     ; This is great! So how do we get the return value of this??
     ; Once you invoke this function the return value is stored in eax.
     ; mov RetValue,eax 
     ; Now RetValue has the returned data, which you can check:
     ; .if(RetValue==IDOK)

We just discussed a few ways to use ASM. Of course, there is many more properties, methods, and functions that exist in ASM, but these are the most common methods.

First Windows Program

Next we'll discuss how to create your first Windows Program in MASM32. This is going to look quite complex at first, but I assure you, it is extremely simple and I will explain each line. Do not be afraid of the length and size of the code, it will all make sense once you read through this tutorial. I chose this program, because it is quite a simple program, and yet has enough examples of every ASM concept.

The following program will kill the process notepad.exe if it is running. You can change it to whatever program by editing the db variables.

.586
.model flat,stdcall
option casemap:none

.586 is a later processor, but you can experiment trying to be compatible to older processors such as .386 or .486 instruction sets.

   include windows.inc
   include user32.inc
   include kernel32.inc
   include shlwapi.inc
 
   includelib user32.lib
   includelib kernel32.lib
   includelib shlwapi.lib

We included the windows library for windows functions, and various windows libraries that also have specific functions. The .inc extension is similar to .h in C++, which is a header or include file. The .lib extension indicates library files.

Your WinMain function

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

We create the prototype WinMain, which isn't defined yet, we just want to let the program know that we will be using the WinMain function later in the program. WinMain is a specific function that the Windows Operating System uses for most of your code.

.data
   ClassName db "MainWinClass",0
   AppName  db "Main Window",0
   ProcessName db "notepad.exe",0
   started db "KillProcess",0
   startedtext db "KillProcess has started!",0
   quittext db "KillProcess is suiciding!",0
   successtext db "KillProcess has succeeded in killing notepad.exe!",0
   failedtext db "KillProcess has failed and brought shame to our family!",0
.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

We express our data here. Usually these are constants and texts that we will be using throughout the program. The .data? variables are undeclared global (the whole program can see them) variables that we will use.

.code
 
start:
	invoke GetModuleHandle, NULL
	mov    hInstance,eax
 
	invoke GetCommandLine
	mov    CommandLine,eax
 
	invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
	invoke ExitProcess,eax

We start our main code, and we invoke or launch some standard windows functions and add the returned values to hInstance and CommandLine.

Shutting Off a Win32 Process

KillProcess proc lpszExecutable:LPSTR
	LOCAL bLoop:BOOL
	LOCAL bResult:BOOL
	LOCAL pe32:PROCESSENTRY32
	LOCAL hProcess:HANDLE
	LOCAL hProcesses:HANDLE
	mov bLoop,TRUE
	mov bResult,FALSE
	mov pe32.dwSize,SIZEOF PROCESSENTRY32
	invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
	mov hProcess,eax
	mov hProcesses,eax

We declare some variables in our KillProcess process function. Which has an argument called lpszExecutable, of the type LPSTR (which is a type of pointer string in windows).
We declare some local variables using the keyword LOCAL, with types BOOL, PROCESSENTRY32, and HANDLE.
We use the mov command to move values of TRUE, or the SIZEOF PROCESSENTRY32 into their appropriate variables.

SIZEOF PROCESSENTRY32 is required because PROCESSENTRY32 is a structure and we want to declare the size of the structure we will be using in our functions. This is required by windows functions.
Many of the types and arguments you will see for each function are just peices of rules that Windows requires from the programmer in order to use certain functions. You can always look them up in MSDN, although you will have to convert them to ASM.

We invoke the function CreateToolhelp32Snapshot, with arguments TH32CS_SNAPPROCESS which is a definition number and 0. The value returned by CreateToolhelp32Snapshot is stored in eax register. So we mov the returned value into a variable we can use for later called hProcess and hProcesses.

Basic Task Manager Processes

	invoke Process32First,hProcesses,ADDR pe32
	.IF eax
		.WHILE bLoop
			invoke CompareString,LOCALE_USER_DEFAULT,NORM_IGNORECASE,ADDR pe32.szExeFile,-1,lpszExecutable,-1
			.IF eax==2
				invoke OpenProcess,PROCESS_TERMINATE,FALSE,ADDR pe32.th32ProcessID
				.IF eax!=NULL
					invoke TerminateProcess,hProcess,0
					invoke CloseHandle,hProcess
					mov bResult,TRUE;
				.endif
			.endif
			invoke Process32Next,hProcesses,ADDR pe32
			mov bLoop,eax
		.endw
		invoke CloseHandle,hProcesses
	.endif
	mov eax,bResult
	ret
KillProcess endp

We invoke Process32First with the variable hProcesses, and we reference the pe32 structure we had started declaring. This is called a struct because it is a blob of data that contains many properties. Earlier we defined dwSize for pe32, since it now contains information we have to use a reference when showing it to other functions. We don't want to literally send the whole struct into the other function, we just want to reference it, so the function can see it and edit the variable/struct from inside the function.

After that, the code checks if eax exists, and then loops as long as bLoop is TRUE. We CompareString to find the program we are looking for, it continues to loop until it finds the program we're looking for in the process list, which is found from Process32 functions.

If the returned value of CompareString is 2, we call OpenProcess, and prepare to terminate it. If we can open this process, then we can go ahead and Terminate it.

If we successfully terminated the program we will equate bResult to true, so we will know later that we were successful.

After we end our if statements using endif, we use Process32Next to continue to the next Process. If there is a next process, we continue to loop using bLoop as true; if not, bLoop will be set as false and the loop will end.

We of course call CloseHandle to stop any memory leaks and clean up our mess. The method ret is used to indicate the end the KillProcess function.

Windows Process Handling

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
	LOCAL wc:WNDCLASSEX
	LOCAL msg:MSG
	LOCAL hwnd:HWND
 
	mov   wc.cbSize,SIZEOF WNDCLASSEX
	mov   wc.style, CS_HREDRAW or CS_VREDRAW
	mov   wc.lpfnWndProc, OFFSET WndProc
	mov   wc.cbClsExtra,NULL
	mov   wc.cbWndExtra,NULL
	push  hInstance
	pop   wc.hInstance
	mov   wc.hbrBackground,COLOR_BTNFACE+1
	mov   wc.lpszMenuName,NULL
	mov   wc.lpszClassName,OFFSET ClassName
 
	invoke LoadIcon,NULL,IDI_APPLICATION
	mov   wc.hIcon,eax
	mov   wc.hIconSm,eax
 
	invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax
 
	invoke RegisterClassEx, addr wc
	INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
	mov   hwnd,eax
 
	invoke ShowWindow, hwnd,SW_SHOWNORMAL
	invoke UpdateWindow, hwnd
 
	.WHILE TRUE
		invoke GetMessage, ADDR msg,NULL,0,0
		.BREAK .IF (!eax)
		invoke TranslateMessage, ADDR msg
		invoke DispatchMessage, ADDR msg
	.ENDW
 
	mov     eax,msg.wParam
	ret
WinMain endp

WinMain is a standard design of all Windows Main functions. The idea is to declare some information for the Windows Operating system, and register our program as a process in the operating system. We then show the window, and start the process loop that handles all incoming and outgoing messages of your program.

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
 
	LOCAL bResult:BOOL
	LOCAL bLoop:BOOL
	.IF uMsg==WM_DESTROY
		invoke PostQuitMessage,NULL
	.ELSEIF uMsg==WM_CREATE
		mov eax,FALSE
		mov bResult,eax
		invoke MessageBox,0,OFFSET startedtext,OFFSET started,MB_OK
		invoke KillProcess,OFFSET ProcessName
		mov bResult,eax
		.IF bResult==FALSE
			invoke MessageBox,0,OFFSET failedtext,OFFSET started,MB_OK
		.ELSE
			invoke MessageBox,0,OFFSET successtext,OFFSET started,MB_OK
		.ENDIF
		mov bLoop,FALSE
		.WHILE !bLoop
			invoke GetAsyncKeyState,VK_ESCAPE
			.IF  eax < 0
				invoke MessageBox,0,OFFSET quittext,OFFSET started,MB_OK
				invoke SendMessage,hWnd,WM_DESTROY,0,0
				mov bLoop,TRUE
			.ENDIF
		.ENDW
		ret
	.ELSE
		invoke DefWindowProc,hWnd,uMsg,wParam,lParam		
		ret
	.ENDIF
 
	xor eax,eax
	ret
WndProc endp
 
 
end start

The WndProc is a standard windows function which we use to handle all the messages that windows or other programs send us. If windows or a program, sends us the WM_DESTROY message, it means someone wants our program to end, and we should handle our shut down operations. If we receive WM_CREATE it means our program just started and we should create the GUI (Graphical User Interface) of the program if it has one.
Otherwise we just run the DefWindowProc (Default Window Process) if no message is being received.

In WM_CREATE we first define bResult as FALSE, so we know when it is true. We invoke a MessageBox to show the user and then launch our KillProcess function. We show a different message box on fail and on the success of KillProcess. We use GetAsyncKeyState,VK_ESCAPE and loop it to wait for the user to press his keyboard Escape key, if that is the case, we shut down our program by sending a message to ourselves called WM_DESTROY. We also show a small good bye message box too.

When you compile that program, you will understand it a little better. Of course, for many it will be confusing but playing around with the code will allow you to learn how ASM works and pretty soon you will understand it.

Also be advised, ASM is a very difficult language, so don't expect to understand it immediately, it may take some time to sink in.


5
Average: 5 (2 votes)
»
  • Share Tutorial

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <img> <ul> <ol> <li> <dl> <dt> <dd> <h3> <h4> <h2>
  • Lines and paragraphs break automatically.
  • Image links with 'rel="lightbox"' in the <a> tag will appear in a Lightbox when clicked on.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • You can use BBCode tags in the text. URLs will automatically be converted to links.
  • Table of contents based on the <h*> tags

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
               .o88o.   .ooooo.    ooooo   ooooo  ooooo     ooo    .oooo.   
888 `" 888' `Y88. `888' `888' `888' `8' .dP""Y88b
ooo. .oo. o888oo 888 888 888 888 888 8 ]8P'
`888P"Y88b 888 `Vbood888 888ooooo888 888 8 <88b.
888 888 888 888' 888 888 888 8 `88b.
888 888 888 .88P' 888 888 `88. .8' o. .88P
o888o o888o o888o .oP' o888o o888o `YbodP' `8bd88P'


Enter the code depicted in ASCII art style.

Navigation

  • Home
  • Forums
  • Image Gallery
  • Links
  • About
  • Contact

Why Register? Contribute articles and tutorials to ID, earn titles, learn from ID programming projects, and advertise your blog in our forums.

  • Forum Community
  • Register Now
  • Write an Article


Copyright © Inferno Development 2008-2009. All Rights Reserved.