Friday, February 21, 2020 | Toby Opferman

WIN32 Programming for TASM Part 1

Toby Opferman

                         Win32 Assembly Introduction
                                (TASM v5.0)

                "Functions, Defines, and Variable Defintions"

        This tutor is for those who know Win32 API programming in
C, C++ or simular language, know the concepts of Event-Driven
programming, have a working knowledge of the basic Win32 API, and
know assembly who want to learn Win32 assembly.  If you do not know
Event Driven programming, read the tutor I wrote on GUI - Event Driven
programming OR get a book on beginning windows programming.

        First off, I want to explain that programming Assembly for
Win32 can be as easy as programming C.  So, we will start with the API
and how to use the definitions.

Before you can start programming Win32 Assembly, you need to define
structures and functions.  When using C, all this is done for you, you
just #include <windows.h> and done!  Well, in Assembly, unless you
search the web or you have an assembler other than tasm that may have
.INC's, you have to define all your prodecures & structures. Luckily,
tasm does have a WIN32.INC which does define a lot of data types
and a few functions (But not many).  Under TASM\EXAMPLES\WAP32
you will find WIN32.INC. You can use this and add on to it.  That
is a lot better than starting off with nothing.

We will start with how to define functions.  This is quite simple, just:

extrn BeginPaint:PROC

That's it! Remeber, Win32 IS case sensitive in some areas, and this is
one of them.

CALL BeginPaint   ; A Call To Begin Paint

Simple.  We will get to parameters in a bit.

But, there is one catch.


UNICODE is something I do not really know a lot about.  It has something
to do with the way Character strings are stored.  There are two types:


UniCode defines the wide character form.  If you have the C header files,
you can do a GREP (This comes with TASM) on UNICODE and you will see
how functions are redefined.  I assume ANSI for all my programs.

Wide character for (I think) means each character is 2 bytes instead of one.
But I am not sure, if someone knows UNICODE and wants to explain it totally
please email me.

So, when you define any function that has String Input, you MUST define it
with either an A on the end or a W on the end. (I always do A cause I use ANSI)

extrn TextOutA:PROC

That is how TextOut would be defined.  Now, you would have to:

CALL TextOutA  ; Call to Text Out Ansi

Of course,to avoid the annoying A/W thing you can:

 TextOut equ <TextOutA>

Then Just

CALL TextOut  ; Call To Text Out

If your program wanted to change to Wide character then, you would
only have to change the extrn and equ instead of the whole program
so this is a good idea and good practice.

Next on the list is defining the Data types/structures.
Well, that's simple.  It would be a good idea to have a API reference
with the Functions & Data type defines structures so you can define
them in your program.  Or, if you have a windows C compiler like Watcom
or Visual C you may grep -w <yourword> directory\*.h  to find structure
defines so you may define them in your WIN32.INC.

Defining Structures:

    msHWND          UINT    ?
    msMESSAGE       UINT    ?
    msWPARAM        UINT    ?
    msLPARAM        ULONG   ?
    msTIME          ULONG   ?
    msPT            ULONG   2 dup(?)

Defining Types:

 HDC equ <dd>

Now, I will show you how to pass parameters.
There is a function of TASM 5.0 to pass like high level, with all
your parms in the call:


This is a bit TOO high level for me, might as well start using
C, and Asm in Win32 is High Level Enough!!
But, if you like that way, you can use that way.  Here is the 
Manual way:

(P.S. I would do a  L equ <LONG>  so you can use on the Pushes
to make sure that dword parms are pushed as dwords if you push
a VALUE or Value Defintion like equ's. Pushing offsets, memory locations
or registers is fine since the compiler will know the size.)

CALL GetMessage    ; Call Get Message

Now, you see that the parameters are pushed on backwards.

in C:

GetMessage(&Msg, 0, 0, 0); // 0 or NULL

Anyway, you see that the parameters are pushed on backwards.

  If you like the C 'NULL' idea

  NULL equ <0>   ; C Sytle Null's

All return values are in EAX.  So, as in our example, you know that the
GetMessage returns a ZERO when your application quits.

  PUSH L 0
  PUSH L 0
  PUSH L 0
  CALL GetMessage       ; Call To GetMessage

  TEST EAX, EAX         ; Quit Loop?
  JZ SHORT EndProgram

  CALL TranslateMessage ; Translate Message

  CALL DispatchMessage  ; Dispatch Message

  JMP SHORT MessageLoop  

  PUSH [Msg.wParam]
  CALL ExitProcess      ; End Program

As you see, the Return value of GetMessage is in EAX.

That is the jist of getting started.  All you need to know from this tutor is:

 1. How to define variables & API Function Definitions including ANSI/WIDE character modes.
 2. How to successfully pass parameters, call and get a return value from an API function

If you have accomplished these, you are ready to move on to my Win32 Intermediate programming
tutor which tells how to create a Win32 Program.

About Toby Opferman

Professional software engineer with over 15 years...

Learn more »
Codeproject Articles

Programming related articles...

Articles »

Resume »

Email: codeproject(at)opferman(dot)com