Hey guys,

So I'm having trouble linking my C code with my ASM code.
In asm I have a proc I wish to use from C.

read_input PROC PUBLIC
enter 0,0
...
leave
ret
read_input ENDP


and in C I have:
#include <stdio.h>
int main(int argc, char **argv){
const int MAX_SIZE = 20;
int array;
extern int read_input(int, int*);
read_input(MAX_SIZE,array);
return 0;
}


I compile my ASM code with:
ml /c /coff asm_file.asm


I try to compile my C file with gcc, and the following command:
gcc main.c asm_file.obj


And I get an error:
D:\DOCUME~1\Admin\LOCALS~1\Temp/ccEXbaaa.o(.text+0x69):main.c: undefined reference to `read_input'
collect2: ld returned 1 exit status


Ive tried so many things but nothing seems to work and http://www.goosee.com/goosee/x86/gcc_masm.htm did'nt help either...

Any ideas? Perhaps a good site to read about how to put it all together successfully?

Thanks!

Edit: I guess  I forgot to mention what I'm using to do all this.

MASM for ASM compiling
GCC for C compiling and C+ASM linking
Posted on 2005-11-24 11:32:59 by ZATRiX
try this exampls from Microsoft
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/vcorimasmsamples.asp
Posted on 2005-11-24 11:46:56 by mistronr1
I don't know how to do that with gcc, but here are 2 fast workarounds:

1) copy the function to the c source itself and compile it then.
2) write a DLL in asm. link to it from C
Posted on 2005-11-24 11:49:31 by ti_mo_n
thanks for the link mistronr1

@ti_mo_n - Well its a school project so I have to follow intructions, but I just found something. Our prof provides us with IO.Mac file to use in ASM for getting input from keyboard. When I remove any reference to the Mac file from my asm code and go through the compiling and linking procedure with my C code, it compiles just fine! :shock:

any ideas about that?
Posted on 2005-11-24 11:55:15 by ZATRiX
the io.mac contains stuff which you're not using, or it's being linked somewhere else.
Posted on 2005-11-24 12:46:42 by ti_mo_n
ya it seems so, so I've abandoned using his macro file, and instead ive just started using printf/scanf right from asm

thanks though!

eidt:

by anychance does anybody know what registers scanf modifies after it is run within asm, because it seems that using it, is a huge hastle!!!
Posted on 2005-11-24 12:49:26 by ZATRiX
win32 functions usually preserve ebx esi edi ebp esp. the rest can be modified.
Posted on 2005-11-24 14:38:08 by ti_mo_n
well something totally messed up is going on, and ive spent way too much time on it already


sub EBX,EBX
push EBX
push OFFSET debug
call printf
pop EBX
pop EBX

..yields "0" on the screen


sub EBX,EBX

push OFFSET var
push OFFSET var2
call scanf
pop EDX
pop EDX

push EBX
push OFFSET debug
call printf
pop EBX
pop EBX


now suddenly EBX becomes some huge number, even though it wasnt directly touched. I've looked at EAX, ECX, and EDX, and they are all affected by the running of scanf, does that make sense? should I abandon using scanf and use something easier? and if so, what is easier to use than scanf in asm.
Posted on 2005-11-24 14:42:45 by ZATRiX
xor ebx, ebx ; ebx = 0
push ebx
push offset string
call printf


You don't pop the values after using them in call.
Posted on 2005-11-24 14:59:12 by Lenin
Lenin: scanf is in cdecl convention (at least in C library that is) so you have to pop the values.

ZATRiX:
Security Note   When reading a string with scanf, always specify a width for the %s format (for example, "32%s" instead of "%s"); otherwise, improperly formatted input can easily cause a buffer overrun. Alternately, consider using fgets.


Try not popping the values - maybe it's stdcall C library?  :shock:
Posted on 2005-11-24 15:01:38 by ti_mo_n

xor ebx, ebx ; ebx = 0
push ebx
push offset string
call printf


You don't pop the values after using them in call.


you mean I dont? because I do
or do you mean I'm not supposed?


edit:

what does "stdcall" mean?
Posted on 2005-11-24 15:05:13 by ZATRiX


push EBX
push OFFSET debug
call printf
pop EBX
pop EBX


its absolutely legal for a function being called to modify its parameters.
If you dont want ebx to be modified you should code


push EBX
push OFFSET debug
call printf
add esp,2*4

Posted on 2005-11-24 15:19:05 by japheth
what does "stdcall" mean?

STDCALL, CDECL and FASTCALL are 3 most popular calling conventions. They specify how the functions get parameters, return the return values and which registers they may/may not modify.

(...)

LoL I forgot about it ^^" You're, of course, right ;)

ZATRiX: I was like: You push ebx, the function (scanf) modifies its parameter, returns, and then you pop the modified ebx. Instead of popping, just balance the stack (using japheth's method above).
Posted on 2005-11-24 16:11:01 by ti_mo_n
ZATRiX,

There are a few basic things wrong with the format of the MASM module you have in mind. When you use a MASM "proc" it already handles the stack frame for you so using ENTER and LEAVE within that proc is not required. The problem with the MACRO does not make sense, if you build the MASM code into an object module, the macro has already been converted to the opcodes it assumes.

The things you must do is match the calling convention between the C prototype you use and the procedure in MASM. Select if you want to use STDCALL or C calling convention, write the C prototype to match and write the MASM procedure with the SAME calling convention.

MyProc proc STDCALL args etc ....

or

MyProc proc C args etc ....

Depending on the characteristics of the C compiler make sure you prototype the masm modules as EXTERN so you don't get name mangling and it all should work.

Note that when you use a PROC in MASM that it handles the stack frame for you. If it is a STDCALL convention used, masm does the following,

LEAVE
RET   This matches the input stack parameters.

With a C calling convention the code only does the RET as the C compiler will balance the stack with an ADD ESP,
Posted on 2005-11-24 17:48:02 by hutch--
@hutch--,

thanks a lot for the explanation. I guess I should explain my macro problem better, as I now understand it.
I have a io.mac file and an io.obj file, but io.mac when compiled does not equal the io.obj provided. The obj contains raw methods the prof wrote and compiled a long time ago apparently, where as the io.mac contains just encapsulated versions of the procs that were compiled into the obj file.

But since the obj file wasnt compiled with the coff option gcc doesnt recognize its presence in my asm obj file and cant find the procs im trying to refer to....
Posted on 2005-11-24 18:17:09 by ZATRiX
There is a bit of trickery that may help you here. A Microsoft linker when you build a library will convert an OMF module to COFF with a warning and this may allow you to link in the library rather than just the object modules.
Posted on 2005-11-25 02:00:37 by hutch--

There is a bit of trickery that may help you here. A Microsoft linker when you build a library will convert an OMF module to COFF with a warning and this may allow you to link in the library rather than just the object modules.


which Microsoft linker are you refering to? and is there any additional info you can provide?

edit:

I found http://www.masmforum.com/simple/index.php?topic=2100.msg16716, but it doesnt seem to solve my problem, but ill look into it further before making conclusions
Posted on 2005-11-25 18:21:37 by ZATRiX
which Microsoft linker are you refering to? and is there any additional info you can provide?


ZATRiX,

The linker supplied with the Masm32 package, Version 5.12.8078 can handle OMF modules to convert them to MS COFF

Can you post your whole project as a zip attachment?

Posted on 2005-11-26 03:54:34 by Vortex

which Microsoft linker are you refering to? and is there any additional info you can provide?


ZATRiX,

The linker supplied with the Masm32 package, Version 5.12.8078 can handle OMF modules to convert them to MS COFF

Can you post your whole project as a zip attachment?


sure!

http://www.scs.carleton.ca/~okarpus/ASM_3.zip

this is all bare bones, the IO.OBJ is exactly how provided to us by the prof.
Posted on 2005-11-26 13:23:18 by ZATRiX
ZATRiX,

Analyzing your io.obj module, I noticed that it's 16-bit code :

_TEXT segment word use16 public 'CODE' ;size is 746
_TEXT ends
_DATA segment word use16 public 'DATA' ;size is 282
_DATA ends
DGROUP group _DATA

public PROC_GETSTR
public PROC_NWLN
public PROC_PUTINT
public PROC_PUTLINT
public PROC_GETLINT
public PROC_GETINT
public PROC_PUTSTR
public PROC_GETCH
public PROC_PUTCH
public TEMP
_TEXT segment
assume CS:_TEXT
PROC_PUTCH:
  push DX
  mov DL,AL
  mov AH,2
  int 021h
  pop DX
  ret


You are trying to combine 16-bit code with 32-bit :

.386 ; <----- 32-bit code
.387  ; <----- 32-bit code
.MODEL FLAT, C
.DATA
.CODE
INCLUDE io.mac
read_input PROC PUBLIC
enter 0,0
GetLInt EAX
leave
ret
read_input ENDP
Posted on 2005-11-27 03:02:31 by Vortex