FASM Tutorial (16 & 32 Bit)

=================
FASM Tutorial
=================

Late at night…
July 22, 2010

by Jakash3

As my choice assembler, I find fasm to be an excellent and simplified program.
It is especially great for beginners and uses the well known intel style asm
syntax for Windows. For this tutorial, I will be demonstrating the creation
of console applications with fasm assembly in both 16 and 32 bit assembly
format.

Let’s start with the simple 16-bit version. In 16-bit assembly, we have 2 byte
registers and we fill the 1 byte AH register with a number that represents a
sub-function to execute when calling an interrupt. Additional parameters for
that function are placed in various other registers, normally those registers
would be the general purpose registers but sometimes it may also be the source
and destination index registers (SI and DI).

Let’s take a look at a hello world com file in fasm assembly:

org 100h

mov ah,09
mov dx,msg
int 21h
mov ah,08
int 21h
int 20h
msg db "hello world!$"

We know that all com file executable code starts at offset 0×100, so that’s
what we place as the first line of code. Org 100h means origin (I think), the
specified number will be the address of where the program will start at. Also
notice that hexadecimal number values have an ‘h’ prefixed after the value.

After that we begin our com file where all our data and code goes in one
segment. Assembly code syntaxing looks standard,

mov ah,09  ;Place value 9 into ah register, index of sub-function to print str
mov dx,msg ;Place address of msg variable reference into dx for str to print
int 21h    ;Execute interrupt call to print the string
mov ah,08  ;Value 8 into ah, sub-function to wait for character input (pause)
int 21h    ;Execute interrupt call
int 20h    ;Exit com file
msg db "hello world!$"  ;The $ terminated string whose address will be
;referenced with the 'msg' keyword.

Simple enough right? But if you want more memory but still use 16 bit code,
you’re going to have to break out of com files and use MZ format EXE programs.
The MZ executable format does not have code starting at 0×100 like com files,
and instead of a 64k limitation, MZ exe files now have more memory to have up
to 4 segments of 64k memory. Each of these segments have their address
referenced in the following registers:

CS = Code Segment
DS = Data Segment
ES = Extra Segment
SS = Stack Segment

To use the MZ exe format in your assembly code, just use the format keyword
specifier in fasm like in the following example:

format MZ

entry main:start            ; program entry point
stack 100h                ; stack size

segment main                ; main program segment
start:
mov    ax,text
mov    ds,ax
mov    dx,hello
call    extra:write_text
mov    ax,4C00h
int    21h
segment text
hello db 'Hello world!',24h
segment extra
write_text:
mov    ah,9
int    21h
retf

Notice that I’m using different segments here. I specify I’m in a new segment
using the ‘segment’ keyword followed by the desired name of the segment. If
you take a look at Ralf Brown’s Interrupt List, you see that the int 21/ah=09
function parameter for printing the string is: DS:DX -> ‘$’-terminated string
That means the segment pointed to by ds plus the offset found in dx, must
point to the string that’s terminated with ‘$’. Now in com files, everything
lies in one segment so we didn’t have to worry about that. But now we’re
dealing with different segments so we must change the value of the ds register
so that ds (base segment address) + dx (offset address) = the address of
data that we are referencing when preparing to print a string.

So in that program, we moved the address of the text segment into ax, and
copied that value into the ds register

Since the hello message lies in a different segment, then “mov dx,hello”
operation would put the address revelevant to text segment into dx. hello is
the first data declared after declaring the text segment therefore that data
lies at an offset of 0 from text. So the segment:offset address of hello is
text:0000. From here we call a label within another segment by declaring the
full segment:offset addr to call and then print the string, return and exit.

Moving on to 32 bit fasm is where it gets a little interesting. Now in 32-bit
assembly, we do not call interrupts anymore; instead, we have to call dll
functions. We do so by pushing the arguments to the stack and then issueing
the call. In this example I will utilize the msvcrt.dll library from the C-
Language runtime.

format PE console
entry main

include 'macro/import32.inc'

section '.data' data readable writeable
msg db "hello world!",0
p db "pause>nul",0

section '.code' code readable executable
main:
push ebp
mov ebp,esp
sub ebp,4
mov dword [esp],msg
call [printf]
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]

section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,\
printf,'printf',\
system,'system',\
exit,'exit'

Ok so, first we introduce the format of the executable. This is a PE format
executable console application (There’s also format PE GUI). “entry main”
specifies the label at which we will start in our program, I used main.

Here we include an include file that comes with fasm. The fasm assembler
gets the path of the include file according to that inf conig file that comes
in the root directory of the fasm download. import32.inc contains macro
definitions that allow us to easily reference and import dll functions.
In other words, it allows us to use the ‘library’ and ‘import’ macros.

now for our data section, the 4th statement means that this section contains
non-executable data that we can read and write to during run-time. Inside this
section, I’ve declared 2 variables names msg and p, each of these variables
end with a null character.

Now for our readable and executable code section. Starting with our entrypoint
label main, I set up a stack frame and allocate 4 bytes on the stack by
subtracting 4 from the value of esp. Now in that 4 byte range I place the
address of msg in there and call printf, Next I place the address of the data
for the pause command on that same area (overwriting the previous address for
my msg data) and then I call system. Then I call exit with the dword (int)
argument 0 on the stack. Now this is all not needed, I just want to show you
how the stack and dll calls work. I personally prefer this method as it really
shows what’s going on and it strives to save memory space by reusing old
blocks of memory that has been placed on the stack.

An easier method goes like this:

push msg
call [printf]
push p
call [system]
push 0
call [exit]

Simple: I push arguments, I call the function. It may not make much of a
difference in this application, but With each push I’m subtracting 4 from esp
and thus memory addressing could add up and become complicated on the stack.
Unless you are a l337 user like me fine tuning data on the stack, this is not
suggested. Otherwise, have fun pushing it…if you know what I mean.

Now another simple method for newbies is to use the ‘invoke’ macro which is
found in the ‘macro/proc32.inc’ include file. It’s as if you’re calling a
function from a high level language.

invoke printf,msg

invoke calls the function. The first argument is the name of the function and
the rest are the aruments for that function. An important thing to note is
that when calling dll functions, the required arguments must be pushed in
reverse order from last to first. So if I needed to call printf with 2
argument pointers: “Your name is %s”,name
Then I will need to do this:

push name
push msg
call [printf]

However, in the case of using invoke, this macro automatically pushes the args
in reverse order for you. So you can call it normally like this:
invoke printf,msg,name

As for actually importing dlls before doing this, you declare your imports in
the ‘.idata’ section. I used the macros library and import. Library macro
(found in import32.inc) allows me to import a dll name specifier. With each
pair of arguments for the library macro, I specify the associated name of that
dll and then the actual name of that dll.

For import, the first argument must be an associated dll name, following that,
each pair of arguments would be the name the desired specifier for a function,
followed by the actual name of that function found in the dll. Notice that I
also used backslashes to expand my one line statement on multiple lines for
easier readability.

Well that’s it for this tutorial, check out these 2 samples of 32 bit asm and
their equivalent C code:

Name.asm:

format PE console
entry main
include 'macro/import32.inc'

section '.data' data readable writeable
msg db "Enter your name: ",0
chrarr db "%s",0
msg2 db "Hello %s",0dh,0ah,0
p db "pause",0

section '.code' code readable executable

main:
push ebp
mov ebp,esp
sub esp,24
mov dword [esp],msg
call [printf]
lea eax,[ebp-12]
mov dword [esp+4],eax
mov dword [esp],chrarr
call [scanf]
mov dword [esp],msg2
call [printf]
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]

section '.idata' import data readable
library msvcrt,'msvcrt.dll'

import msvcrt,\
printf,'printf',\
scanf,'scanf',\
system,'system',\
exit,'exit'

Name.C:

#include "stdio.h"
#include "stdlib.h"

int main() {
char name[12];
printf("Enter your name: ");
scanf("%s",name);
printf("Hello %s\n",name);
system("pause");
return 0;
}

Loop.asm:

format PE console
entry main

include 'macro/import32.inc'

section '.data' data readable writeable
intl db "%d",0dh,0ah,0
p db "pause>nul",0

section '.code' code readable executable
main:
push ebp
mov ebp,esp
sub esp,12
mov dword [ebp-4],1
loopA:
mov eax,dword [ebp-4]
cmp eax,11
jge BreakA
mov eax,dword [ebp-4]
mov dword [esp+4],eax
mov dword [esp],intl
call [printf]
mov eax,dword [ebp-4]
inc eax
mov dword [ebp-4],eax
jmp loopA
BreakA:
add esp,4
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]

section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,\
printf,'printf',\
scanf,'scanf',\
system,'system',\
exit,'exit'

Loop.C:

#include "stdio.h"
#include "stdlib.h"

int main() {
int i;
for (i=1;i<11;i++) {
printf("%d\n",i);
}
system("pause>nul");
return 0;
}

18 thoughts on “FASM Tutorial (16 & 32 Bit)

  1. Thanks a lot for this tutorial. It was extremely helpful. This is the first fasm tutorial on the web for newbies. I would love a follow up wit a program collects user input(e.g name) and diplays output based on the input(e.g “hello (name)). Thanx. Awaiting reply

    • 16-bit FASM:

      org 100h
      mov ah,09              ;print string
      mov dx,prompt          ;string to print
      int 21h
      mov ah,0ah             ;Buffered input
      mov dx,max             ;points to dos input buffer struct
      int 21h
      mov ah,09
      mov dx,msg
      int 21h                ;print "Hello, "
      mov ah,09
      mov dx,input           ;print '$' user's input
      int 21h
      mov ah,08              ;pause for single char input
      int 21h
      int 20h                ;exit
      
      prompt db "Enter name: $"
      msg db 0dh,0ah,"Hello, $"
      
      ;DOS input buffer structure
      max db 50              ;max chars buffer can hold
      read db 00             ;number of chars read from last input
      input db 50 dup (24h)  ;actual buffer that stores user input
      ;buffer filled with '$' for input termination for
      ;print string function.
      

      32-bit FASM:

      format PE console
      include 'macro/import32.inc'
      entry main
      
      section '.text' code readable executable
      main:
      push ebp
      mov ebp,esp              ;Create stack frame
      sub esp,60               ;allocate 60 bytes
      mov dword [esp],prompt   ;arg: &prompt on top of stack
      call [printf]
      lea ebx,[ebp-50]         ;First 50 bytes on stack is where
      mov dword [esp],ebx      ;the input buffer is stored
      call [gets]
      mov dword [esp],msg      ;arg1: &msg
      mov dword [esp+4],ebx    ;arg2: pointer value of %s token
      call [printf]
      mov dword [esp],p        ;pause
      call [system]
      mov esp,ebp
      pop ebp                  ;restore stack frame
      mov eax,0                ;return value 0
      ret                      ;return from main
      
      section '.data' data readable writable
      prompt db "Enter name: ",0
      msg db "Hello, %s ",0
      p db "pause>nul",0
      
      section '.idata' import data readable
      library msvcrt,'msvcrt.dll'
      import msvcrt,\
      printf,'printf',\
      gets,'gets',\
      system,'system',\
      exit,'exit'
      
      • how can i do a out put something like this
        Enter name: john
        hello, john
        Enter name: im good
        that’s cool

  2. Master! Master! Teach us :)
    At last! The best fasm tutorial i’ve ever seen…
    I hope that it will be more tutorials in future x)

    There are some tutorials for nasm.. tasm… but fasm (which I like the most:)…
    well, it looks like it is forgotten and abandoned by people :(

  3. I dont understand.. The system call I’m getting program crash >.NUL”,0
    section ‘.code’ code readable executable
    invoke system,p
    invoke exit,0
    section ‘.idata’ import data readable
    library msvcrt,’msvcrt.dll’
    import msvcrt,system,’system’,exit,’exit’

  4. thanks for the update. i was wondering how to get further info on using fasm(like the libraries and their functions) especially with 64bit. 32bit help would also be appreciated, thanks

  5. Whenever I try to run the 32-bit programs after assembling them, my antivirus says it has found a virus in the program. Any ideas?

  6. How do you get a new line with these macros, and if there isn’t an actual way how would you do it with just regular asm with no macros

  7. Not really for beginners but its a start. I like fasm coz its small and doesnt involve alot of preliminary settings before you use it. I run it at work (even though i dont have admin privs) and at home. The beginner tuts are the only thing missing…I would pay for one btw

  8. Thanks for the tutorial, just one thing so far which irritated me a little bit ;)

    “Also notice that hexadecimal number values have an ‘h’ prefixed after the value.”
    I am pretty sure a “prefix” cannot be “after” something, I believe we do use the word “suffix” in that case :)

    Good tutorial otherwise, thanks!

    Clem

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: