I just started learning assembly, and I wanted to be able to create a function in assembly (using nasm) and call it in a C++ program...So I tried to create a simple function:


;test.asm
segment .text
global _test_func

_test_func:
enter 0,0
add dword [esp+4],4
mov eax,[esp+4]
leave
ret


Now, I don't know if that is even the correct way to create a function, but I can't even get it to link with my program correctly:


//test.cpp
#include <iostream>
using namespace std;
int test_func(int n);

int main()
{
cout<<test_func(4);
}


So I assemble with nasm

nasmw -f coff test.asm

and I'm using dev c++ so I created a project and added the test.o file in Project Options->Parameters->Linker

When I try to compile I get the errors:

undefined reference to test_funct(int)
multiple definition of main

I've also tried compiling directly with g++:

g++ -o test test.cpp test.o

Which gives me the same errors, plus a bunch of others along the lines of "undefined reference to std::cout"

Can anyone point me in the right direction?
Posted on 2003-11-28 21:14:19 by JaWiB
Hi,

#include <iostream.h>

/**
* since we calling a c function from cpp code. Inform the compiler
*/

#ifdef __cplusplus
extern "C" {
#endif

int test_func( int a ) ;

#ifdef __cplusplus
}
#endif

int main()
{
int i ;

i = test_func( 5 ) ;

cout << i ;

return 0 ;
}

============ assembly ===========

section .text

global _test_func

_test_func:

push ebp
mov ebp, esp


mov eax, 4

leave
ret

=================================


Compile normally and link it properly. I run with VC, without any pain.



regards
cult
Posted on 2003-11-28 23:37:44 by cult
Check out Ultrano's wrapper macros for coding oop classes in asm.. he designed them as an aid to calling asm from c and vice versa. I use them to code c classes in asm, callable from asm or c.
Posted on 2003-11-29 00:40:38 by Homer
Thanks for your reply, Cult! I tried it on VC++ and got it to work, and then went back to Dev C++ and now it works there too :)

I'm a bit confused now, though. What defines a C++ function as opposed to a C function?
Posted on 2003-11-29 14:13:23 by JaWiB
Ah, never mind it - C++ functions can be included in different ways in oop objects, defined by classes (c++ structures). C++ is necessary in apps, where you need to created objects dynamically, and a lot of other stuff.
After all, C++ can be described as C with some macros for oop.
Posted on 2003-11-29 18:34:51 by Ultrano
i do not undertand very well what you are traing to do but a function in a dll is just like this using NASM and NAGOA macros :


;===================== [ full dll with 2 arguments ]

%include "\lab\vasm\inc\nagoa.inc"

global DllMain
global MsgBox
export MsgBox



rotin DllMain,hInstDLL,fdwReason,lpvReserved
mov eax,TRUE
endrotin

proc MsgBox,title,info
call MessageBoxA,0,,,MB_OK
call ExitProcess,0
endproc
;============================ [ end of dll code ] ======









by the way without macros the code of a function with N arguments is like this:

FunctionName:

%define arg_1 ebp+8
%define arg_2 ebp+12
%define arg_3 ebp+16
%define arg_4 ebp+20
.
.
;so on adding always 4 bytes (32 bits ) for the next argument
;stack is organised 32 bits



enter 0,0 ;making stack frame , push ebp in the stack and mov esp to ebp
; esp is stack pointer



; here you use the arguments....
; mov dword eax,


;the end of the function we store the stack

leave ; destroys a stack frame we made it is MOV_ESP,EBP followed by POP_EBP

ret N*4 ; if we have 4 arguments is 4*4=16 so we do -> RET 16


;===============================================









well we can also make functions without EBP ...

like this:

;================================
FunctionName:

%define esp+4 arg_1
%define esp+8 arg_2
%define esp+12 arg_3
%define esp+16 arg_4

; here we do not need the stack frame :)

; use the arguments...
; mov dword eax,


ret 4*4 ; ret 4* Number of arguments


;=================================




when a function is CALLED

push dword arg_4
push dword arg_3
push dword arg_2
push dword arg_1

the stack can be observed like this :

esp+12 | arg_4
esp+8 | arg_3
esp+4 | arg_2
esp | arg_1

CALL FunctionName


and now we CALL and the stack is like this :


esp+16 | arg_4
esp+12 | arg_3
esp+8 | arg_2
esp+4 | arg_1
esp | return adress


so know we are at the FunctionName...


FunctionName:

mov dword eax, ; we move the value of arg_1 in to eax register :)
; use the 4 arguments here
etc...

ret 16




ret 16 will make the esp "walk" in the stack 16 bytes from the stack pointer ( esp )


lets see



esp+16 | arg_4 ; 4+4+4+4 bytes = 16 bytes
esp+12 | arg_3 ; 4+4+4 bytes
esp+8 | arg_2 ; 4+4 bytes
esp+4 | arg_1 ; 4 bytes
esp | return adress ; zero


well now the stack looks like it was before the call to our function.




but it is much more secure to use the satck frame !!!







we can look at the stack like this :









positive part of the stack were arguments of functions are
=========================================
negative part of the satck were locals variables are





so for example:

is a argument
is a local variable





thats all

NASM ROCKS ! :)
Posted on 2003-11-29 20:06:39 by Nguga
I understand most of that pretty well I think, but I'm still confused about something...

My question is how do I make the function so I can declare it in the C++ program?

/**
* since we calling a c function from cpp code. Inform the compiler
*/

#ifdef __cplusplus
extern "C" {
#endif


Why do I have to do that? Is there some naming convention I have to follow to declare C++ functions in asm?
Posted on 2003-11-29 23:11:35 by JaWiB
supose we made a function in assembly NASM called dllcomArg.dll

;===================== [ full dll with 2 arguments ]

%include "\lab\vasm\inc\nagoa.inc"

global DllMain
global MsgBox
export MsgBox



rotin DllMain,hInstDLL,fdwReason,lpvReserved
mov eax,TRUE
endrotin

proc MsgBox,title,info
call MessageBoxA,0,,,MB_OK
call ExitProcess,0
endproc
;============================ [ end of dll code ] ======




to call that function in side c++



#define WIN32_LEAN_AND_MEAN

#include "windows.h"

typedef UINT (CALLBACK* LPFNDLLFUNC1)(LPSTR,LPSTR);

int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
LPFNDLLFUNC1 NgugaMSG;
HINSTANCE hDLL;

hDLL = LoadLibrary("dllcomArg.dll");

NgugaMSG = (LPFNDLLFUNC1)GetProcAddress(hDLL,"MsgBox");

NgugaMSG("Afinal sempre funciona","Ola");

return 1;
}
Posted on 2003-11-30 06:16:41 by Nguga
I'm not talking about a dll, I want to write a function in a *.asm file and assemble it into a *.obj so I can link it with my program. Do I have to use a dll to write a C++ function in asm?
Posted on 2003-11-30 10:53:42 by JaWiB
No need for dlls. Just make a .lib , include it in the c++ project, define the function as
extern "c"
and it's all oki-doki. the above line in fact says the compiler shouldn't expect anything but leading underscore in func name, and optionally @4 at end.
there are many examples on the board on how to do everything precisely, use the "search"
Posted on 2003-11-30 12:12:08 by Ultrano
Hi folks,

Agner Fogs paper on Pentium Optimization (Chapter 3) contains a lot of info on this subject. Look it up. Plus the thread:

http://www.asmcommunity.net/board/index.php?topic=16181

might also help if you are coding for VB.

Regards,
Art
Posted on 2003-12-01 20:57:28 by art_sands
Hi Nguga! and all interested in this topic

You'v done a good job about dll using in C++!
but is it possible to link it not dinamicaly ,just static like a.lib?

I have a conflict because of the same name of a dlls and want to do static linking in one program and to be not warry about enything else.

/\/\/\/
harry
Posted on 2003-12-04 03:52:58 by HarryTuttle