VOGONS


First post, by Harry Potter

User metadata
Rank Oldbie
Rank
Oldbie

Hi! I want to port a library for 8-bit computers to DOS. The library is simply an efficient replacement for the standard C text functions. I have OW C, Turbo C, Digital Mars C and NASM. I need to call some assembler code from C. Moreover, I want to declare the functions as __fastcall. How do I pass the parameters and handle the stack?

Joseph Rose, a.k.a. Harry Potter
Working magic in the computer community

Reply 1 of 11, by vstrakh

User metadata
Rank Member
Rank
Member

As far as I know there is no fastcall conventions in Turbo C.
It did appear in Borland C++ (Turbo C++?), but that's past the Turbo C lifetime.

Reply 2 of 11, by Harry Potter

User metadata
Rank Oldbie
Rank
Oldbie

I really want to write this program using __fastcall, as it would be a little more efficient. So, how do I handle the stack? I want this for the 16-bit x86 microprocessors.

Joseph Rose, a.k.a. Harry Potter
Working magic in the computer community

Reply 3 of 11, by vstrakh

User metadata
Rank Member
Rank
Member

You can write programs with whatever conventions available from your compiler, but you must stick to the original conventions used in the libraries you're trying to replace.
And fastcall was not standardized anyway. It can differ across the compilers, so there's no point in using it in public APIs.

With Turbo C it would be correct to push all the arguments on stack in reverse order (for cdecl function), and expect the returned results in AX, or DX:AX.
When returning the structures the actual method depends on the structure size, small structures are packed into AX or DX:AX registers, larger structures are passed via statically allocated buffer, returning pointer in DX:AX for far pointers or AX for near pointer. Turbo C usually just copies structure bodies, without implementing any kind of RVO.
You are free to clobber all registers except BP, and you must restore SI/DI if you clobbered those when "register variables" optimization is enabled.

Reply 5 of 11, by vstrakh

User metadata
Rank Member
Rank
Member

Really, you should check with docs for the actual compiler you will be using, since there are no "standard C libraries" outside of the context of specific compiler's environment.
Bitsavers has manuals (user and reference guides) for many tools from Borland for sure.

Reply 6 of 11, by Harry Potter

User metadata
Rank Oldbie
Rank
Oldbie

I have OW 2.0 and Borland C/C++ 1.0 (I think) and 3.0. I didn't install the source code for OW, and I don't know about Borland. I want to analyze the source code for functions such as puts() and getchar() to see what I should better and what I don't need to do. Where can I find the spurce code for the Borland compilers? BTW, the library would be implementation-specific but should have the same names and parameters.

Joseph Rose, a.k.a. Harry Potter
Working magic in the computer community

Reply 7 of 11, by Harry Potter

User metadata
Rank Oldbie
Rank
Oldbie

I really want to code much of the library in assembler and declare it as __fastcall. How do I use the parameters defined by __fastcall? BTW, I have Pacific C. Should I code for it? I remember discovering that it pushes the last parameter to a function in AX or DX:AX.

Joseph Rose, a.k.a. Harry Potter
Working magic in the computer community

Reply 8 of 11, by Ringding

User metadata
Rank Member
Rank
Member

Just write the function in C, then disassemble it, and you will be able to figure out which parameters go where from it. If not, then I question your ability to write the entire function in assembler in the first place.

Reply 9 of 11, by maxtherabbit

User metadata
Rank l33t
Rank
l33t
Ringding wrote on 2022-11-24, 16:24:

Just write the function in C, then disassemble it, and you will be able to figure out which parameters go where from it. If not, then I question your ability to write the entire function in assembler in the first place.

What? I know full well how to write x86 assembly but basically zero experience in disassembly. They are different disciplines

Reply 10 of 11, by Grzyb

User metadata
Rank Oldbie
Rank
Oldbie
maxtherabbit wrote on 2022-11-24, 22:51:

What? I know full well how to write x86 assembly but basically zero experience in disassembly. They are different disciplines

Actually, there's no need to disassemble anything.
Most C compilers provide an option for ASM output, eg. "gcc -S"

Nie tylko, jak widzicie, w tym trudność, że nie zdołacie wejść na moją górę, lecz i w tym, że ja do was cały zejść nie mogę, gdyż schodząc, gubię po drodze to, co miałem donieść.

Reply 11 of 11, by Ringding

User metadata
Rank Member
Rank
Member

Actually just declaring the function and calling it from somewhere and looking at the resulting assembler code should give you everything you need.

Most C compilers provide an option for ASM output, eg. "gcc -S"

Yes, but disassembly is often more readable, at least to me, because it is not littered with hard-to-decipher assembler macros and other magic that allows the linker to turn the entire thing into something that actually works.