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.cThis 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.sWe'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.sNow, 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!