# help with nasm code

This topic is 3961 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to do some assembly programming so my first goal is to be able to call an assembly function from C++. Here is what I have so far: test.cpp
#include <iostream>
using namespace std;

extern "C" int TimesThree(int i);

int main()
{
int x=5;
x=TimesThree(x);
cout<<x<<endl;

return 0;
}


tt.asm:
global _TimesThree

_TimesThree:
push	ebp
mov	ebp, esp
mov	eax, [ebp+8]
imul	eax, [eax], 3
leave
ret


so what I do is: nasm -f obj tt.asm cl /EHsc test.cpp tt.obj it gives a warning about converting OMF to COFF but if I try to fix that by changing nasm's output format to coff it doesn't work. So anyway and exe is produced but it always crashes. I am assuming that it is in the assembly code but I think that I followed the description of how to do the C calling convention in the nasm docs pretty well Well if anyone knows how to fix this please help.

##### Share on other sites
According to this snippet from the NASM manual, Chapter 6: Output Formats

Quote:
 Note that although Microsoft say that Win32 object files follow the COFF (Common Object File Format) standard, the object files produced by Microsoft Win32 compilers are not compatible with COFF linkers such as DJGPP's, and vice versa. This is due to a difference of opinion over the precise semantics of PC-relative relocations. To produce COFF files suitable for DJGPP, use NASM's coff output format; conversely, the coff format does not produce object files that Win32 linkers can generate correct output from.

Poking around these google results, the solution appears to be either switch to MASM or switch to GCC or some non-microsoft compiler/linker.

##### Share on other sites
I am not exactly sure what leave does behind the scenes... I think it fiddles with the stack pointer for use with local variables.

When I have written assembly functions that were called from C I have never used the leave instruction.

I have always used

pop EBP
ret

Try running the debugger and step through in disassembly mode and see where the crash is occuring.

Edit: The little assembler snippet relates to the __cdecl calling convention. The calling function is responsible for adjusting ESP.

(This is purely from memory so feel free to correct me if I am mistaken)

[Edited by - Adam Hamilton on March 19, 2007 5:00:48 PM]

##### Share on other sites
Quote:
 Original post by Adam HamiltonI am not exactly sure what leave does behind the scenes... I think it fiddles with the stack pointer for use with local variables.

Quoth the Intel manuals... "The LEAVE instruction copies the frame pointer (in the EBP register) into the stack pointer register (ESP), which releases the stack space allocated to the stack frame. The old frame pointer (the frame pointer for the calling procedure that was saved by the ENTER instruction) is then popped from the stack into the EBP register, restoring the calling procedure's stack frame"

It's perfectly valid to have both (NASM syntax)

foo:    PUSH  EBP    MOV   EBP, ESP    ; Allocate local variable space on the stack (SUB, normally)    CALL  bar    ; Free local variable space on the stack (ADD, normally)    POP   EBP    RETbar:    ENTER 0,   0    ; 0 bytes of local variables, first nesting level    INC   EAX    LEAVE           ; Cleanup    RET

Or, indeed, some combination thereof - although I suspect you might want to be careful with using LEAVE without a matching ENTER (EDIT: Slightly more careful perusal of the manuals pseudocode statement of the operation suggests that this is actually okay, so long as you manually keep track of the nesting levels (if appropriate)).

I'm more used to hand writing the second, although if I'm mixing ASM with C code, I'm more used to my particular GCC cross compiler using the former so I stick with that.

##### Share on other sites
thanks everyone, still having problems though

So I triedI fooling around with trying to get OMT/obj to work by adding BITS 32 but it didn't work, so I tried MinGW (g++)

I went to the minGW page (worst website ever) and downloaded the stuff. I installed it and added it to my path, but it didn't want to work so I am calling it with the full name. So I tried to get a minimal C++ program running but it wanted a WinMain instead of a main so I ended up with the following:

#include <iostream>using namespace std;extern "C" int TimesThree(int i);#include <windows.h>   int WINAPI WinMain (HINSTANCE hInstance,                        HINSTANCE hPrevInstance,                        PSTR szCmdLine,                        int iCmdShow)   {      //MessageBox (NULL, "Hello", "Hello Demo", MB_OK);	int x=5;	cout<<TimesThree(x)<<endl;	      return (0);   }

and my tt.asm as before, though I added the BITS 32
BITS 32global _TimesThree_TimesThree:	push	ebp	mov	ebp, esp	mov	eax, [ebp+8]	imul	eax, [eax], 3	leave	ret

then I used:

nasm -f coff tt.asm
\MinGW\bin\g++ -o test.exe test.cpp tt.o

for the error I get:

(.text+0x114): undefined reference to `TimesThree'

##### Share on other sites
Edit: Got rid of chunk of post cause it wasn't clear
Try this:

global _TimesThree

_TimesThree:
push ebp
mov ebp, esp
mov eax, [ebp+8]
imul eax, [eax], 3
pop ebp
ret

##### Share on other sites

This topic is 3961 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

This topic is now closed to further replies.