interfacing with c/c++: problem solved

karim, i finally solved my problem. (after 2 months that is...) this is something for the curious before i leave. first of all, i won't tell you the data type, such as return values (what registers it should be in ect...) but i will tell you the layout and then you're on your own (f0dder told me that you should do the research yourself. don't be lazy - that's where learning comes). (this is my note. it's not a tutorial. )

first of all, TurboC++ was my target, everything i know about Visual C++ doesn't work with Turbo C++. therefore, to really interface with Turbo C++, you have to use TASM (it's possible with MASM, which i'm still trying to figure it out right now) but even if masm works with turboc++, i don't think it's a good idea that you combine MS and Borland together. Borland understood Turbo C++ more than Microsoft, whereas Microsoft understood VC++ much more than Borland (i'm talking about the inner and how it was created). therefore, if you're interfacing with turbo c++ or turbo pascal, use TASM. and use MASM if you're interfacing with Microsoft C/C++ or Visual C++, don't try to mix them. (guess what? it works perfectly fine if you use MASM and interface it with Turbo Pascal)

(repnz stosb <--- compiled fine with tasm, but not with masm. tasm is playing smart. that's not what most people want...)

ok. i'll explain Turbo C++ first (cause it's kind of confusing):

take a look at c:\tc\lib and you'll see alot of *.obj file. the following are important:

Object File Library File TCC Option
COT.OBJ CS.LIB -mt ;tiny
COS.OBJ CS.LIB -ms ;small
COM.OBJ CM.LIB -mm ;medium
COC.OBJ CC.LIB -mc ;compact
COL.OBJ CL.LIB -ml ;large
COH.OBJ CH.LIB -mh ;huge

note: the character after the C is a number zero. c0t.obj <-- c, zero, t and then .obj and you must know what you're doing with those object file when you link them together. there's two ways by the way, one is to link those object together or you can do it with TCC option which i believe is easier (save typing).

here's an example:


IDEAL ;tasm mode
MODEL SMALL ;you'll be using -ms (know the memory module you're using)

public _winamp

proc _winamp near
arg yourArg1:dword, yourArg2:dword

push bp
mov bp, sp


pop bp
endp _winamp



#include <stdio.h>

extern void winamp(unsigned char *somearg, .....);

void main()
///do something about it

now, here's what you do: create an obj file of module with tasm:

tasm /ml module.asm ; and you'll get module.obj next is caller.c
tcc -c caller.c ; -c compile only
tcc -ms caller.obj module.obj ;this will combine caller.obj and module.obj with Model Small (-ms) together and it will produce an exe automatically.

and now, on to Microsoft C/C++ and Visual C++

Microsoft Visual C++ is a 32bit compiler, therefore, you have to play by the rule (rule that you've been playing all these years...)

parameters struc
dw ? ; pushed BP
dw ? ; return address
;place argument here
parameters ends

.model small
;place data here

public _procname

_procname proc near

mov bp, sp



_procname endp


the layout above is for Microsoft C/C++ (i didn't test it. but i believe that's how it goes). a note on struct: parameters struct doesn't create exe size. only if you use it. for example:

parameters struc
dw ?
dw ?
arg1 dw ?
parameters ends

..somewhere in proc

mov ax, [bp+arg1] ;much more readable than: [bp+somevalue]

to make it works with Visual C++, just change the model to: .model flat, stdcall and you're done! (don't forget to create an obj file with masm: masm /c /Cp myasmfile.asm) and use it in VC++ without linking (the Turbo C++ way)

that's it. i know i missed alot of details here, but hope you understand... (i'm out of energy now)


parms struc
dw ?
dw ?
arg1 dw ?
parms ends

and use it as this: mov reg, <-- correct way

my result to masm with turbo c++: failed. there's a big problem with *.obj file. therefore, masm won't work if you interface it with turbo c++ 3.0 (that's the version i'm using) cause Turbo C++ report that your asm *.obj is a bad object file. what i did was compile my asm with ml and then link it with tcc. it has a big conflict, so i try link16 (of masm) and link both together, but this time, there's a problem with turbo c++ library, therefore, it halt my system to dealth .

anyway, that's it. that's my conclusion based on my observation. (i guess you have to use tasm for turboc++...)
Posted on 2001-08-01 12:48:57 by disease_2000
Hi Disease, I don't understand the role of the parameters structure. Is it used to access the argument passed by the 32-bit function ? If yes, there is a problem because the argument list starts at , and you can't access with BP because it's 16 bit.
If you want my opinion, do it either 16-bit or 32-bit, but don't mix both of them. Good luck !
Posted on 2001-08-01 15:13:46 by Dr. Manhattan
at the time of writting that, i didn't have enough energy. and about the parms, don't try to use that with TASM. (my research on masm and turboc++ is messed up now. (i forgot to protect the c library (make it readonly) when my system halt, it destroy that file. )

thank for the reply. i'll look forward for that. (i have no problem using struct in this form:

parms struc
dw ?
dw ?
arg1 ?
parms end

and then use it this way:

mov reg,
Posted on 2001-08-01 15:27:16 by disease_2000
There's a few things to be aware of if you mix compilers/linkers/assemblers.
First of all, never ever mix 16 and 32bit code. Will end up pretty wrong :).
Next, there's the name decoration schemes. Figure out what your
assembler and compiler wants... remember that almost any flavor
of C requires you to an underscore as the first char in the name of
the asm proc ... but not in the C proc.

extern "C" int myFunc(void)

will be

_myFunc PROC
_myFunc ENDP

in masm.
Also, you will need to make sure masm doesn't fux0r up the names.
It has a habit of adding @stacksize to all your names. I can't really
remember how to turn this off, but it's trivial to find in the masm32
docs. I'm convinced it has to do with .model .
Posted on 2001-08-02 21:19:26 by f0dder

unsigned int add(unsigned int input); // no EXTERN is need

That's right, but I would add it anyway, just to show that this is
not a forward-prototype to code that will appear later in the c file.
Also, you will probably *have* to do the extern when compiling .cpp
files, since a lot of name mangling is added otherwise.

Also, why are you using structs to reference locals? Doesn't tasm
have automatic support like masm? It's a while since I used tasm
last, but I seem to remember automatic variable support...

masm can do 16bit code as well as tasm... masm has the advantage
of not being stuck with the OMF format in 32bit mode, but sporting
the wonderful coff format... which isn't a m$ invention.

the "masm mode" in tasm doesn't mean we have a masm hiding
inside tasm. It's only part of the syntax that changes -- not assembler-
dependant stuff like model and so on.

TASM doesn't understand the OPTION directive (even when you're in MASM mode - perhaps, future version of TASM will),

TASM is a discontinued project.

therefore, don't bother. cause every INCLUDE/INCLUDELIB file will be a disaster without the OPTION CASEMAP on. so, for 32bit app - following iczelion's tutorial - you have to use masm compiler.

Not really. But you need a set of header/library files written for tasm. As fro "option casemap", have you ever looked at what parameters
tasm.exe takes? Perhaps you should investigate the /ml switch...

however, if TASM is your choice and you want to develop your app in 100% TASM, sure you can! just play by the rule (TASM) in an area that needed and get back into MASM mode and do your thing the MASM way and then switch back to IDEAL whenever needed.

If you want to, why not just code everything in IDEAL mode???

masm obj file doesn't get along with turbo c++'s obj file

can't see why this is so. Unless of course you're trying to link 16bit
OMF with 32bit coff... :). If you get both assemblers to produce OMF,
and use 16bit in both, there shouldn't really be any problems. Ok,
the OMF format allows for vendor-specific sh!t in the OMF files, but
use a decent linker and you will have no problems.

Ah well. If you want to use tasm, go ahead. Can't really see why you
would want to, though. It's old and unsupported, has a bunch of
(crash) bugs, and doesn't support the new instruction sets (and
don't tell me about the macros, I know about them).
Posted on 2001-08-02 22:16:36 by f0dder
Ummm, where did the "guest" post made by disease_2k just go?
Posted on 2001-08-02 22:17:27 by f0dder

Ummm, where did the "guest" post made by disease_2k just go?

he choose to ban himself from the forums and so it shall be
Posted on 2001-08-02 22:50:12 by Hiroshimator
:/. He had some information in there... though a bit flawed and not
all that useful :).
Posted on 2001-08-02 23:59:06 by f0dder
just to show you what i usually do when i want to use asm code in c :

i create a regular masm code :

.model flat,stdcall




proc1 proc uses what i want, param1:dword, param2:dword,....


proc1 endp

then i compile with /c /Coff /Gd to put in c call format (no decoration to the name) for example in myproc.obj

then in msvc++, i go in the project properties and i add myproc.obj to the link edit box (where there are all the .lib). then at the beginning of the code i put :

extern proc1(param1:long,param2:long,....);

and it' s all done, you just have to do :

Posted on 2001-08-03 02:56:22 by roy
I dont have time to read everything posted in this thread, but i just spent the night learning to write external code for pascal. This tut has a section on how to do it for c and pascal.
Posted on 2001-08-03 03:34:27 by ChimpFace9000