• Please review our updated Terms and Rules here

Help needed with writing an AIL/32 driver: dummy driver works in ASM, but not in C

If you look in the source code you will see the assembly code uses the invoke pseudo op to call the pre-declared routines. This matches the calling convention of the routine so you don't have to manage the parameter passing details by hand.

To figure out why your dll isn't being loaded, a few well placed printfs in the loaddll routine ought to identify what it doesn't like. Hexdump would also be your friend here. It doesn't look to be a particularly complex parsing of the dll to get it to load
 
Good one! Another puzzle piece. I didn't know that Watcom defaulted to its own proprietary calling convention.
The C source and header files of the AIL/32 SDK and driver sources have the `cdecl` keyword in all function declarations and definitions. This includes `ail32.h`, which is the driver API. So I guess that answers that question. I guess it makes sense to standardize on the "C declaration" calling convention for this driver model, since 32-bit DOS protected mode applications and games that would make use of these drivers were typically written in C or C++.

I'll adjust my code to include the `cdecl` keyword in all the function declarations. Thanks for that!

However, I don't think that explains why the driver loading code isn't at least detecting the copyright string at the top of the file, past the first 32 bits that contain the pointer to the driver index.

As for catching a C call in assembly: if I'm going to keep an assembly shim and defer to C code from there, I'll need to do the opposite: call C functions from assembly code. Can anybody maybe share an example of how to do that, assuming the C calling convention (`cdecl`)? Thanks again!

I recommend keeping the assembly shim to ensure that the driver is structured exactly as required. It's much easier to make an assembler emit exactly what you want, compared to a C compiler.
 
If you look in the source code you will see the assembly code uses the invoke pseudo op to call the pre-declared routines. This matches the calling convention of the routine so you don't have to manage the parameter passing details by hand.

To figure out why your dll isn't being loaded, a few well placed printfs in the loaddll routine ought to identify what it doesn't like. Hexdump would also be your friend here. It doesn't look to be a particularly complex parsing of the dll to get it to load

Yes, that's what I had been doing: adding printf statements and comparing the outputs with a hex viewer. But it was still unclear why exactly it failed to load.

I recommend keeping the assembly shim to ensure that the driver is structured exactly as required. It's much easier to make an assembler emit exactly what you want, compared to a C compiler.

That's what I ended up doing. And the good news: it worked! In fact, I got it working with both DJGPP and the Open Watcom (v2) compilers.

However, I ran into a limitation: I didn't have access to the standard C library (stdlib) that came with those compilers. To build a properly loadable AIL/32 driver DLL, I need to use either Watcom's wlink or the JWLink fork by Japheth a.ka. Baron-von-Riedesel. The reason being that the object files need to be linked into an OS/2 LX DLL, since that's the binary format that the DLL loader of the AIL/32 driver framework expects. Both those linkers need to be explicitly told where to find the C library file that implements stdio.h for use in DOS executables. Apparently, the standard C libraries that both the DJPP and Watcom compilers provide for building DOS projects seem to require a main() function. In addition to that, the C library of DJGPP also appears to require some symbols that are missing in my project. The C code I'm using in the project is just library code, to be called from the assembly shim, and therefore shouldn't need a main() entrypoint. And even if I provide a dummy main() function so that it at least works with Watcom, it once again results in an DLL that the DLL loader can't load. (That's with Watcom. With DJGPP it still wouldn't build at all, because it was missing other symbols that I somehow couldn't provide in my C code.)

Not being able to use the standard provided C libraries of these compilers will complicate things a bit, since I'll have to provide any libraries and such myself. Perhaps I can use something like Picolibc to offer C library functionality in my project instead?
Also, if anybody knows how I can use DJGPP's linker to link the object files into that LX DLL format, preferably in a way that would still allow me to use the standard C library that comes with DJGPP, please let me know.

I'm making progress step by step. 😅 Again, thank you all for your help so far!
 
There's PDPCLIB, a Public Domain C runtime library written by Paul Edwards, which should support the Watcom toolchain, and it aparently had an update on SourceForge as recently as 2019, and that seems to fit the bill. It's supports DOS, and is 32-bit safe. I'm trying to build that.
 
Last edited:
Well, that that didn't work...

I'm just going to try porting some driver sources from FreeBSD or Linux and see if I can provide or even implement any stdlib functions that those functions might need.

Please let me know if you have any better suggestions. Thanks.
 
Are you using the nostdlib compile option to avoid pulling in stdlib? Not sure what each compiler uses for the exact compiler flag, but it should be something like that.
 
Are you using the nostdlib compile option to avoid pulling in stdlib? Not sure what each compiler uses for the exact compiler flag, but it should be something like that.

I think that was going okay when compiling PDPCLIB. That was not the problem I ran into, since there were Makefiles included that already included the "don't provide stdlib" compiler parameter. I just couldn't get it to build an object file that didn't have any 16-bit segment stuff in it. But ultimately, I actually do want stdlib to be included without having to supply a portable alternative implementation. I was just trying that as a workaround, due to the fact that the stdlib implementations of both DJGPP and Watcom tend to include C Runtime (CRT) stuff, which expects certain symbols that aren't in the DLL library project that I'm trying to build.
 
Back
Top