Tuesday 27 September 2011

Small steps in assembly

The first thing most people really want to do in assembly is connect it to normal C code (or the high level language of your choice).  Assembly is all well and good, but no one wants to rewrite the OS (unless you do...in which case there are many other places you should be heading to).

Let's start then with two straight forward programs.  One piece of assembly we can call from C, and one that is the main program and that then calls a C function.

Calling Assembly from C
The first piece of C code looks very simple, namely:
#include <stdio.h>

extern    int    assemAdd( int input );

void main( void )
{
    printf( "%d\n", assemAdd( 57 ) );
}
assemAdd.c

This piece of code simply calls an external function - namely assemAdd - which we'll implement in assembly. It passes 57 to the function and prints the result.

Let's have a look at the assembly code:
global    _assemAdd

section .text

_assemAdd:
    mov    eax, [ esp + 4 ]
    add    eax, 5
    ret
assemAdd.s

We'll go through what the assembly code does line by line in detail next time (mainly because I'm going to have to discuss calling conventions), but we'll get this built and check the outcome.

Here's how we build these file and run the resulting executable:
$ nasm -f win32 assemAdd.s
$ gcc assemAdd.c assemAdd.obj -o assemAdd.exe
$ ./assemAdd.exe
62
$

The first line assembles the assemAdd.s file into the win32 format (because we're running this on Windows). This will produce an assemAdd.obj file.

The second line will compile the assemAdd.c file, and link the resulting object file with the assemAdd.obj file created by nasm.

It then creates the assemAdd.exe executable, which we run and see our output. As I said, we'll be going through this in detail next time, but see if you can work out what's happening on your own.

Calling C from Assembly
In this example we're going to create an assembly program that calls one of the libc methods - namely printf. Again, we'll go into detail next but for now we'll get something working:
global    _main

extern    _printf


section    .data

printStr:    
    db    'This is a test print', 0

section .text

_main:
    push    ebp
    mov     ebp, esp
    push    printStr
    call    _printf
    leave
    ret
assemMain.s

Now, if we assemble this using nasm we can link it using gcc. Gcc, by default, will automatically include libc into the build unless told not to, so we don't have to do anything complicated:
$ nasm -f win32 assemMain.s
$ gcc assemMain.obj -o assemMain.exe
$ ./assemMain.exe
This is a test print
$

So, there we go. We'll dig into things a little deeper next time (including explaining why assembly functions have a preceding '_') but for now we've managed to get some code built and working. Which is always a good place to start from!

Thursday 22 September 2011

Setting up a development environment

Before we can start playing around with some assembly we're going to download a development environment.  Although I will be playing around with Linux and Mac OS assembly in the future, at present I'm going to stick to Windows to begin with.  This means we're going to need an assembler and a C compiler suite.

Why are we going to use a C compiler suite?  Well, because we're going to link C code to assembly to show how we interact with normal code, and because it provides us with a linker.

Here's what you're going to need:
  1. A text editor.  I suggest Vim but feel free to use your favorite.  If you do end up using Vim, can I suggest you head over to gregsexton.org - one man's love affair with Vim taken to scary new levels.
  2. An assembler.  We're going to use the Netwide Assembler - because it uses the Intel assembly syntax (we'll get to that later) and it's regularly updated.
  3. A C compiler suite.  Cygwin is just too bloated for my liking so I'm going to use MinGW.  You go to the main site here but it's probably easier to go straight here to find the Windows installer.
Make sure that when you install MinGW, that you select the MSYS Basic System as shown below:


Next time we'll look at setting up our MSYS environment so we can use all our tools in the one terminal.

The reason this sprung into life...

This blog is being put together to investigate low level programming techniques.  Originally the aim is to explain basic assembly language concepts to some friends, but hopefully I'll be able to use it as a platform to various programming topics.