The "Go" tools
     The GoAsm manual

for those new to ....

assembly language

by Jeremy Gordon -

If you have only previously tried assembler in 16-bits and hated it - give it another try. Using assembler in 32-bits, particularly in the Windows environment, is easy, clean and fun!

What is assembly language?

Assembly language is a programming language. Programs are written in text form using a text editor (to make "source code"). This source code is read by the "Assembler" and the "Linker" to provide the final executable program.

A feature of assembly language is that each line in the source code usually contains a single instruction to the processor, for example MOV EAX,EDX will move the content of the EDX register into the EAX register. Here the "MOV" instruction is called a "mnemonic". This may seem a pretty basic instruction if you are used only to a higher level language. However, in Windows, you also have the use of a vast high level language (Windows itself). Thus, using Windows and assembler gives you the benefit of both a high level language and also control of the processor - perfect combination!

Why code at such a basic level?

There are several reasons why you may wish to do this:

  • No bloat. By coding at this low level you can reduce the code to the minimum required for the job in hand.
  • Speed. Smaller code size means your programs load quicker and run quicker.
  • Control. You are in control of the code, not the compiler. This means you know exactly what the processor is doing as it moves through your code. This makes it easier to get things right and to spot errors.
  • Satisfaction. You yourself are writing the program. It is not being written in part by the compiler.
The coding components available to you.

You will need to study the instructions which come with your assembler for a full account of these. However, ignoring instructions which would not be used in Windows, conditional assembly, macros, and the floating point, MMX and 64 bit instructions, basically the components can be divided into these categories:

  • Register instructions. This is where you tell the processor to move data or carry out calculations using its own 32-bit registers. There are 6 such registers for general use called EAX, EBX, ECX, EDX, ESI and EDI. Examples of such instructions are:-

    MOV ESI,EBX     ;move contents of EBX register into ESI register
    ADD EAX,EDI     ;add contents of EDI register to EAX register
    BT ECX,0        ;test bit 0 of ECX register
    CMP EDX,450     ;compare contents of EDX with 450
    DIV ECX         ;divide EDX:EAX (long integer) by ECX
    MUL ECX         ;multiply EAX by ECX result in EDX:EAX (long integer)
    SHL EDX,4       ;shift EDX bits to the left by 4 bits (multiply by 16)
    TEST EAX,8      ;test bit 3 of EAX register
    

  • Stack instructions. The stack is an area of memory provided by Windows for each running program to use as a temporary storage area. Examples of such instructions are:-

    PUSH EAX        ;push the contents of EAX register onto the stack
    POP EDX         ;pop the last thing pushed on the stack to EDX
    PUSH 1000h      ;push hex value 1000 on the stack
    MOV EBP,ESP     ;keep current stack pointer in the EBP register
    SUB ESP,30h     ;move the stack pointer to make an area for local data
    MOV D[EBP-20h],500h  ;insert the value 500 hex in the local data area
    

  • Execution instructions. These divert the processor to execute code from a point other than the next line in the source code. Examples are:-

    CALL MAKEWINDOW ;execute the procedure and return afterwards
    CALL EAX        ;execute from EAX code address and return afterwards
    RET             ;finish with this procedure returning to the caller
    JZ 4            ;continue execution from label 4: if result was zero
    JC >.fin        ;continue execution from .fin if carry flag is set
    JMP MAKEWINDOW  ;continue execution from the named procedure
    LOOP 2          ;decrement ECX and jump to label 2: unless ECX=0
    

  • Memory instructions. These read to, or write from, areas of memory other than the stack. Typically this memory may be in the executable's own data section or it could be from memory allocated by Windows at run time. Examples are:-

    ADD EAX,[ESI]     ;add to EAX contents of memory pointed to by ESI
    MOV EAX,[MYDATA]  ;move to EAX contents of memory at the MYDATA label
    SUB D[MYDATA+64],10h   ;subtract 10h at dword at MYDATA plus 64 bytes
    CMP B[MYDATA+EDX*4],2  ;compare a byte with 2 in part of MYDATA array
    LODSB           ;load byte at memory pointed to by ESI into al
    STOSD           ;load the contents of EAX into memory pointed to by EDI
    

  • Flag instructions. The main flags you will use are Z (zero flag), C (carry flag), S (sign flag) and D (direction flag). Most instructions change the flags automatically to give the result of the instruction. There are certain specific instructions you can use to change the processor flags manually:-

    STC              ;set the carry flag
    CLC              ;clear carry flag
    STD              ;set the direction flag for LODS,
                     ;STOS, CMPS, SCAS, MOVS
    CLD              ;clear direction flag
    

  • Declarations of memory. Windows reserves memory for the executable when it runs. Declarations are made to reserve memory in the data section or constant section if the data is to be initialised that is, set to a value. If the data does not have to be initialised the data area can be reserved in the unitialised data section. This does not take up any space in the Exe file. Instead space in memory is allocated for this type of data when the executable first starts.
    Examples of how memory is declared is as follows (some of these differ between Assemblers):-

    DB 4             ;declare a byte and set to initial value 4
    MYDATA DB 4      ;a byte initial value 4 with data label MYDATA
    MYSTRUCT DD 16 DUP 0   ;16 dwords all set to zero called MYSTRUCT
    BUFFER DB 1024 DUP ?   ;1024 bytes called BUFFER in undefined data
    

  • Instructions to tell the Assembler into which section to put the following source code. The Assembler marks the code section as read-only and executable, and defined and undefined data sections as read/write. Here are examples (this will differ between Assemblers):-

    CODE SECTION     ;all following to be in a section to be marked
                     ;as read-only and executable (code)
    DATA SECTION     ;all following to be in a section with read/write
                     ;attributes but not code attributes
    CONST SECTION    ;all following to be in a section with read
                     ;attributes only
    

  • Comments. Everything after a semi-colon will be ignored, enabling you to describe exactly what your source code is doing and why.

  • Windows instructions. This gives the assembler programmer access to the vast range of Windows APIs (Applications Programming Interface). This is code within the Windows operating system. Examples are:-

    PUSH 12h             ;push hex value 12 onto stack for API call
    CALL GetKeyState     ;ask Windows to get state of Alt key in EAX
    TEST EAX,80000000h   ;test whether Alt key is pressed (bit 31 set)
    JZ >L22              ;no, jump forward to L22
    
    .............
    
    PUSH 24h             ;hex value 24 = question mark, yes and no button
    PUSH ESI,EDI         ;address of title, address of message
    PUSH [hWnd]          ;owner's window handle
    CALL MessageBoxA     ;show Windows message box asking yes/no
    CMP AL,7             ;see if "no" was clicked by the user
    JNZ >L40             ;no, jump forward to L40
    
    .............
    
    PUSH 0
    PUSH ADDR FILE_DONE  ;give address of FILE_DONE to receive result
    PUSH ECX,EDX         ;ECX=bytes to write, EDX=source of data,
    PUSH ESI             ;ESI=file handle
    CALL WriteFile       ;write ECX bytes from EDX to ESI
    
    .............
    
    PUSH 808h,5h         ;808=bottom and filled middle, 5=raised
    PUSH EBX,EDX         ;ebx=RECT, EDX=device context
    CALL DrawEdge        ;draw special edged rectangle to screen
    
    .............
    
    PUSH 4h,3000h,ESI,0  ;4h=make read/write memory, 3000h=reserve
    CALL VirtualAlloc    ;reserve and commit ESI bytes of read/write memory
    
    .............
    
    PUSH 0,[hInst],0,0   ;param, module handle, menu, owner
    PUSH 208,130,30,300  ;height, width, y, x
    PUSH 80C80000h       ;style (POPUP+CAPTION+SYSMENU)
    PUSH EAX             ;EAX=address of zero terminated string with title
    PUSH 'LISTBOX'       ;push pointer to 'LISTBOX'
    PUSH 0               ;extended style (none)
    CALL CreateWindowExA ;create listbox window
    
    
    ...... or if you prefer, you can use INVOKE ..
    
    
    INVOKE CreateWindowExA, 0,'LISTBOX',EAX,80C80000h,300,30,130,208 \
                          0,0,[hInst],0
    
    .............
    
    INVOKE ShowWindow, [hWnd], 1
    
    


    Copyright © Jeremy Gordon 2002-2003
    Back to top