Page 1 of 1

Calling assembly routines from C Rate Topic: -----

#1 Aphex19  Icon User is offline

  • Born again Pastafarian.
  • member icon

Reputation: 615
  • View blog
  • Posts: 1,873
  • Joined: 02-August 09

Posted 15 May 2011 - 10:08 AM

Prerequisites for this tutorial


Tutorial introduction
This tutorial will be a basic demonstration of calling routines written in assembly from your C code. We will use NASM to compile our assembly code and GCC to compile our C code.

The assembly code
For the purpose of this tutorial, our assembly routine will be very simple, it will simply add two integers passed as parameters and return the result.

add.asm
; make the add function visible to the linker
global _add

; prototype: int __cdecl add(int a, int B)/>
; desc: adds two integers and returns the result
_add:
	mov eax, [esp+4]	; get the 2nd parameter off the stack 
	mov edx, [esp+8]	; get the 1st parameter off the stack 
	add eax, edx		; add the parameters, return value in eax
	ret					; return from sub-routine


We are using the __cdecl (default for C/C++) calling convention, so we must take some things into account...
We preserve the stack pointer, this is because the stack is cleaned up by the caller so we don't want to mess around with the stack pointer inside the routine.

The return value is returned in the EAX register.

Leading underscores are added because by default GCC will add these to function calls. We could use GCC compiler flags to change this behaviour but for simplicities sake, we will just add them in here.

The C code
The C code will simply be a basic main function that calls our add function

main.c
#include <stdio.h>

/* 
 * declaring add as extern tells the compiler that the definition
 * can be found in a seperate module 
 */ 
extern int add(int a, int B)/>;

int main() {
	int ret = add(10, 20);
	printf("add returned %d\n", ret);
	return 0;
}


Compilation
Compiling the above code requires the use of object files, the format that we will use is ELF since NASM and GCC both understand this format.

The first thing we must do is compile our assembly code using NASM. We will compile add.asm into an object file called add.o using the following command.

nasm -f elf -o add.o add.asm


Now you should have an ELF file called add.o in your working directory. Next we need to compile our C code, main.c. We use GCC to do this using the following command.

gcc -c main.c -o main.o


Now you should have two object files, add.o and main.o. Now for the final step, we will link these object files together to create our final executable file. To do this, we will use GCC again which in turn will invoke LD for us. The following command will create our executable.

gcc -o test_asm add.o main.o


Now you should have an executable file asm_test.exe which will call our assembly routine and display the result, that is.

Quote

add returned 30


Conclusion
Thanks for reading my tutorial, I hope you got something out of it.

Ryan

Is This A Good Question/Topic? 4
  • +

Replies To: Calling assembly routines from C

#2 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3105
  • View blog
  • Posts: 19,144
  • Joined: 14-September 07

Posted 27 June 2011 - 07:11 PM

Good tutorial.


For those of you compiling on a *nix box, you'll need to add the underscores yourself for compilation:

#include <stdio.h>

/* 
 * declaring add as extern tells the compiler that the definition
 * can be found in a seperate module 
 */ 
extern int _add(int a, int B)/>;

int main() {
	int ret = _add(10, 20);
	printf("add returned %d\n", ret);
	return 0;
}



otherwise you'll get undefined errors for add.


Alternatively, modify the assembly and remove the underscores:

; make the add function visible to the linker
global add

; prototype: int __cdecl add(int a, int B)/>
; desc: adds two integers and returns the result
add:
	mov eax, [esp+4]	; get the 2nd parameter off the stack 
	mov edx, [esp+8]	; get the 1st parameter off the stack 
	add eax, edx		; add the parameters, return value in eax
	ret					; return from sub-routine




nasm 2.07
gcc 4.4.3
Was This Post Helpful? 2
  • +
  • -

#3 Aphex19  Icon User is offline

  • Born again Pastafarian.
  • member icon

Reputation: 615
  • View blog
  • Posts: 1,873
  • Joined: 02-August 09

Posted 28 June 2011 - 03:08 PM

View PostKYA, on 27 June 2011 - 08:11 PM, said:

Good tutorial.


Thanks KYA.
Was This Post Helpful? 0
  • +
  • -

#4 Deca  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 7
  • Joined: 09-July 11

Posted 09 July 2011 - 02:35 PM

thanks
Was This Post Helpful? 0
  • +
  • -

#5 shammancer  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 110
  • Joined: 03-September 10

Posted 22 January 2012 - 06:49 PM

Would this work in c++ as well?
Was This Post Helpful? 0
  • +
  • -

#6 vividexstance  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 665
  • View blog
  • Posts: 2,296
  • Joined: 31-December 10

Posted 24 January 2012 - 10:48 AM

View Postshammancer, on 22 January 2012 - 08:49 PM, said:

Would this work in c++ as well?

Yes, for the most part, if something can be done in C, it can also be done in C++. Many times, if code compiles with a C compiler, but there is a problem with the code, a C++ compiler will usually be able to warn about that problem where the C compiler didn't.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1