Code in Win32 Assembly!!!
This Article has nothing to do with Visual Basic, but a simple answer to those emails i received from PSC members asking how to add Assembly Inline-Code to Visual Basic; i say why learning those when you can actually write your Win32 Assembly Code, in pure TASM format! the article was written in serries, but this is the only part i will be uploading here in PSC cause i am now on my way of designing my own website, soon i will be deleting all of my entries here =(
Podsumowanie AI: This codebase represents a historical implementation of the logic described in the metadata. Our preservation engine analyzes the structure to provide context for modern developers.
<pre>
Introduction to Win32 Assembly Programming
==========================================
By: Chris Vega [gwapo@models.com]
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
What will i learn from this article?
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+- Definitions of Application Programming Interface (API)
+- How to incorporate API to Win32 Assembly, as well as how to convert
VC++ definitions from Win32 API Refference to a Win32 Assembly format
+- How to code a Do-Nothing Application (skeleton) using Win32 Assembly
using Borland TASM 5.0
+- How to compile and link your Application
+- How to show an output in screen saying "Hello World!" using MessageBox
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Introduction
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Hello World! thats what everybody have in mind on every language introduction, so i will
be giving a simple hello world application in Win32 Assembly in this Article, showing
you how to compile and link it using Turbo Assembler (TASM) and explain the details
about the application we have created.
Notes:
+-
This tutorial, as well as other Win32 Assembly Articles in this site are written in
TASM syntax (TASM specific), therefore you need TASM5 to conpile and link the source
codes in this article.
Download TASM here (greetz to, crackstore):
http://www.crackstore.cc/toolz/tasm5_1.zip
http://www.crackstore.cc/toolz/tasm5_2.zip
http://www.crackstore.cc/toolz/tasm5_3.zip
Also, you need a Text Editor, NotePad which is Built-In Windows OS is pretty
useful.
+-
There are various Windows Operating Systems and non of them performs alike, but
with Assembly Coding, the differences are less, so the name "Win32" was purposely
attached to Assembly to describe a Windows Environment Assembly Code - "Win32Asm"
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Application Programming Interface
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Application Programming Interface or simply API is what replaces the Interrupt calls
in the old DOS System, same as Interrupt, APIs are also a functions, but unlike Ints,
APIs "must" be imported into your Application before you can make use of it, i've put
"must" in quote cause APIs can also be called directly from its address without really
importing it to you application, but thats a little advanced topic, so lets concentrate
a more on importing APIs.
In TASM, importing an API was done using the directive "extrn", which is the same direc-
tive used to import external routines, that simplifies the explanation, API is exported
by Dynamic Link Libraries or DLL and APIs are external routines/funtions, therefore in
order to import an API to your application, we can simply add:
extrn ApiNameHere:PROC
or
extrn ApiNameHere:NEAR
As i told earlier, APIs are exported by DLLs, and the rules for case-sensitivity in API
Names are strictly active, thefore:
extrn apiName:PROC
is not the same as
extrn Apiname:PROC
you can find these APIs in Win32 API Refference included in MSDN Library, Visit:
http://msdn.microsoft.com/library
or download the Win32 API Refference (8.5MB) at crackstore:
http://www.crackstore.cc/toolz/win32_1.zip
http://www.crackstore.cc/toolz/win32_2.zip
http://www.crackstore.cc/toolz/win32_3.zip
http://www.crackstore.cc/toolz/win32_4.zip
After downloading and extracting it, or simply open your MSDN on-disk or on-line and
view the most common APIs of all, the ExitProcess
ExitProcess
===========
The ExitProcess function ends a process and all its threads.
VOID ExitProcess(
UINT uExitCode // exit code for all threads
);
In TASM, importing this API is always a must, this is to tell TASM that we are creating
a Win32 Application rather than DOS Programs:
extrn ExitProcess:PROC
Again, case-sensitive check all API names you are typing before you proceed with coding
or else, TASM32 will unable to create import refference of API to your Application, and
with Arguments or Parameter passing, Win32 Assembly always expect right-to-left (RTL) or
Standard Calling Convention (stdcall).
ExitProcess expect 1 parameter, in Assembly, all parameter must be pushed in RTL order,
and all addresses or values aree passed, meaning, lpXXX expect a Long-Pointer, uXXX
expect Unsigned Value etch.
The above C++ definition of ExitProcess API will be converted to Asm as:
push uExitCode ; exit code for all threads
call ExitProcess
APIs are generally grouped with two types, one is the string using API and the other is
not a string using API, meaning, if the API needs string to be passed as an argument, ie,
MessageBox, see the description of MessageBox in Win32 API Refference:
MessageBox
==========
The MessageBox function creates, displays, and operates a message box. The message
box contains an application-defined message and title, plus any combination of
predefined icons and push buttons.
int MessageBox(
HWND hWnd, // handle to owner window
LPCTSTR lpText, // text in message box
LPCTSTR lpCaption, // message box title
UINT uType // message box style
);
LPCTSTR in VC++ is a pointer to a string argument, known in hungarian notation "LP" or
"Long Pointer", meaning, MessageBox API is an string using API, knowing that Windows
Operating System provides two different string types, the ANSI of "A" and the UNICODE
or "W", each string using API always two different versions, one for ANSI and one for
UNICODE, so MessageBox has:
MessageBoxA - ANSI version MessageBox
and
MessageBoxW - UNICODE version MessageBox
this is very significant in Win32 Assembly, since in TASM, these APIs must be declared
first as an "extrn", therefore the correct name is necessary to be imported and not its
"macro" name!
To make it simple, MessageBox doesnt exist in User32.DLL, what exist are MessageBoxA and
MessageBoxW, try to find out by downloading my GetAPI Tool in the Download section of
this site, and try to locate MessageBox or other string API, like CreateFile etch and
amaze yourself by discovering that they doesn't exist, but the ANSI or "A" / UNICODE or
"W" versions.
If you dont want a tool to learn if the API exist by itsname or do it have two versions,
then simply look for the Requirements on the API description from Win32 API Refference,
let see MessageBox:
Requirements:
Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.
Unicode: Implemented as Unicode and ANSI versions on all platforms.
and look at the Unicode label.
For the parameter, all API parameter, exept those User defined are Noted by Hungarian
Notation, ie, "LP" means Long Pointer for String, therefore in Win32 Assembly, LP will
simply be converted to Offset, let see the conversion of MessageBoxA in Win32 Assembly:
push uType ; message box style (DWORD)
push offset lpCaption ; message box title (OFFSET DWORD)
push offset lpText ; text in message box (OFFSET DWORD)
push hWnd ; handle of Owner (DWORD)
call MessageBoxA
and finally, functions return values, and APIs are functions, so values are returned
as a result, most APIs return their result in the register EAX, or EAX contains info
that the result has been passed to certain parameter/s.
simple? yeah, you're right!
On to coding, next
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Do Nothing Code
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Before we go to a full running "Hello World!", let see the skeleton of a Win32 Assembly
Code that does nothing, assuming you save them in "donone.asm":
--------------------------------------------------------------cut here----------------
.386
.model flat, stdcall
extrn ExitProcess:PROC
.data
db ?
.code
start:
call ExitProcess, 0
end start
-----------------------------------------------------------end cut here---------------
The first two lines probably the most important in Win32 coding, because it will tell
the compiler the minimum processor for the application:
.386
.model flat, stdcall
The second line tells the compiler about the memory model using directive ".model", where,
in Win32 Environment, flat is the only memory model, meaning we needs to trash any idea of
segment:offset pairing or whatever memory models you might come accross in your previous
Assembly Coding experiences, and welcome ourselves to the world of selectors or straight
memory layout in 32-bit addressing.
the "stdcall" however tells the TASM our way of Passing Argument, if we omit stdcall, we
have to push all parameters in the RTL order, while using stdcall tells the compiler that
we are about to use Standard Calling Convention as our means of Parameter Passing, it means:
push uExitCode ; exit code for all threads
call ExitProcess
Can be converted to:
call ExitProcess, uExitCode
Therefore, no need to push Parameter to Stack one-by-oe, simply by calling the API and
its arguments all in one line separated be comma(,) Note the comma after the API name.
After the headings, the list of API imports follows - "extrn"s, you must import the needed
APIs to make use of it, at-least thats the idea of Win32 Programming.
.data
db ?
The same as the old layout of assembly coding, we need to define all datas first, inside
the ".data" directive; the "db ?" instruction tells TASM to have a dummy Data Section, or
TASM will gets an error (TASM bug) if your application doesn't included any data at all.
.code
start:
call ExitProcess, 0
end start
After Data is the Code, stated by ".code" directive, followed by the very-first label,
meaning, it doesn't really needed to use "start:" as your starting label, you can use
others like "cvega:", but remember to close this first label using the "end <label>"
instruction, see:
.code
cvega: ; <-- First Label
call ExitProcess, 0
end cvega ; <-- Ending the Starting Label!
Inside the "Starting Label" and "End Label" is the actual code,
call ExitProcess, 0
only tells the machine to Exit this Process, btw, Process is the name given for an
Application Loaded in memory for execution, this is a simple example of how to call
an API inside the actual application.
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Compiling and Linking the Code
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The very first thing in mind in compiling Assembly code in TASM is locate Import32.Lib
file, found at the Lib Directory where TASM5 have been installed, a simple approach is
to copy this file into "bin" directory, where your "tasm32.exe" and "tlink32.exe" are
located, then create a batch file for compiling purpose:
--------------------------------------------------------------cut here----------------
@echo off
tasm32 %1,, /ml /m9 /t
tlink32 %1,,,import32.lib -Tpe -x -c
del *.lst
del *.obj
-----------------------------------------------------------end cut here---------------
And save it also to "bin" directory, named "mk.bat"
To compile "donone.asm" file, simply call:
c:\tasm5\bin\mk donone
from your "bin" directory in your MS-DOS or DOS-BOX, and will automatically create you
a donone.exe, but if you execute it, it will automatically terminated, since ExitProcess
is the only command in this Application, if you found problems about compiling, please
consult the "docs" directory from TASM and read more about compilation and building your
project into exe, using the above batch file is the simpliest method i am using, while
there are more complex approaches, like creating your own MAKE file for use with MAKE.EXE
or even create your own Definition or Library Files.
Parameters used in making a Win32 EXE Application,
tasm32:
/ml = Case-Sensitive on Sysmbols, ml means All-Sysmbols
/m9 = Allow 9 multiple passes to resolve forward references
/t = Suppress messages if successful assembly
tlink32:
-Tpe = Build a PE image, replace this with Tpd to compile DLL
-x = No Map
-c = Case-Sensitive
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Hello World!
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
After our success in a "Do-Nothing" code, which is presented so you have a fully
functional skeleton application in Win32 Assembly coding (everybody needs that!), were
here to create a Hello World Application, let open the "Do-Nothing" code again, and save
it as "msgbox.asm":
--------------------------------------------------------------cut here----------------
.386
.model flat, stdcall
extrn ExitProcess:PROC
.data
db ?
.code
start:
call ExitProcess, 0
end start
-----------------------------------------------------------end cut here---------------
next is the addition of MessageBox API (MessageBoxA), to greet our user "Hello World",
how? simple, add the API as new "extrn" in the API declarations:
.386
.model flat, stdcall
extrn MessageBoxA:PROC ; <-- Added MessageBoxA
extrn ExitProcess:PROC
follow by data declaration in the ".data" dirrective, since MessageBoxA API expects two
String Datas, lpCaption and lpText, both must be daclared:
.data
db ? <-- Remove dummy, we no longer needed it cause we have now an
actuall data of our own.
and replace with
.data
lpCaption db "My First Win32 Application", 0
lpText db "Hello World!", 0
comma and zero (,0) specified that our string is NULL Terminated, and on to the code, by
adding a "call" instruction, just like ExitProcess and all other APIs, Assembly uses
"call" opcode to execute an API function, remember, we no longer needs to follow the
serries of pushes, like:
push uType ; message box style (DWORD)
push offset lpCaption ; message box title (OFFSET DWORD)
push offset lpText ; text in message box (OFFSET DWORD)
push hWnd ; handle of Owner (DWORD)
call MessageBoxA
those are for description purpose nowadays, we can simply call it directly using the
Standard Calling Convetion (stdcall) like:
call MessageBoxA, hWnd, offset lpText, offset lpCaption, uType
or break it to multiple lines for easy code-reading (have no effect on EXE tough!)
call MessageBoxA,\
hWnd,\
offset lpText,\
offset lpCaption,\
uType
In the code, simply follow how do VC++ calls a API:
.code
start:
call MessageBoxA,\
0,\
offset lpText,\
offset lpCaption,\
0
call ExitProcess, 0
end start
The final form of the changes from "Do-Nothing" code to a full "Hello World" application is:
----[msgbox.asm]-----------------------------------------------cut here----------------
.386
.model flat, stdcall
extrn MessageBoxA:PROC
extrn ExitProcess:PROC
.data
lpCaption db "My First Win32 Assembly Application", 0
lpText db "Hello World!", 0
.code
start:
call MessageBoxA,\
0,\
offset lpText,\
offset lpCaption,\
0
call ExitProcess, 0
end start
-----------------------------------------------------------end cut here---------------
compile it again with mk.bat:
c:\tasm5\bin\mk msgbox
and run:
c:\tasm5\bin\msgbox
shows you a no-design MessageBox saying
+--------------------------------------------------------+
|[-] My First Win32 Assembly Application _ [] X |
+--------------------------------------------------------+
| |
| Hello World |
| |
| [ OK ] |
| |
+--------------------------------------------------------+
download the chapter1.zip file.
next chapter, i will explain the detains of MessageBox to show you how to control
flows in Win32 Assembly and how to use return values from API.
Copyright 2001, by Chris Vega [gwapo@models.com]
</pre>