News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

calling c functions from dos

Started by allynm, April 15, 2011, 02:05:16 AM

Previous topic - Next topic

allynm

Hi Dedndave

First, thanks for the code and for thinking about this problem.  This is an interim report from me.  More later.

I copied your modified ("hello") program.  I am using v. 6.15 too.  Also, my 16-bit linker is link16 (which I believe is a renamed version of link563), the same link16 as shows up in the bin directory for MASM32.  As far as I can tell you and I are using exactly the same ml and link commands.

So, coming back to your modified program.  When I do ml /c davetest16.asm, I get an error saying "undefined symbol : DGROUP".  However, if I write ml /c /omf /Fl davetest16.asm, the assembler is happy.  In addition, when I do link16 davetest16.obj, davetest16.exe, the linker is happy too and the code runs and says "hello" just as you would expect.  So I am deeply puzzled.  I can't see why you wouldn't also get the same error message.

What I haven't done yet is to use your .bat file.  I can't see why that should make any difference, but I don't know what else to try.

Again,
Thanks

Mark Allyn

dedndave

well - it should not hurt anything to use the /omf switch
that is the OBJ file format you want, anyways

however, it makes no sense that it is behaving differently on your machine than it is here
perhaps you have an "ML" environment variable that specifies a set of default switches for masm
to find out, open a console window and type....
set ml
and press enter
if the variable is present, it will tell you the value
if not, it will say something like "variable not defined"
if the coff switch appears - there is your answer   :bg

your C compiler installer may have set this variable, so not it may not be a good idea to remove it
there are other ways to work around this problem, like using a batch file SETLOCAL command

adding the following line to the beginning of your 16-bit bath file should disable it
setlocal ml=""
SETLOCAL should affect only the ML variable used during batch execution
(or you can just use /omf for 16-bit batch files - lol)

allynm

Hi Dedndave,

I checked my environment variables and ml is not defined or given a value.  So...   but it was an interesting idea you had and one that I would never have come up with.

I don't mind setting the /omf switch routinely, at any rate, and it solves the problem even though it doesn't explain the problem.  I guess I am just compulsive enough to want to know how these things work.

Back to the problem that got us here, namely how to use the C library off Dos.  I found a c library in an old Watcom compiler package I hadn't used for a long time.  Anyway, when I try to link16 my DOS caller to the library I get a bunch of error messages to the effect that _TEXT : segment size exceeds 64K.  I get one of these for each of the c library functions in the file.

Any idea what might be wrong?

Regards,
Mark Allyn

dedndave

i can't explain that one
the code segment in the asm program may not be named _TEXT, as it was in the old days
if that's the case, do not use ".CODE"
use something like this...
_TEXT   SEGMENT WORD PUBLIC 'CODE'
        ASSUME  CS:_TEXT,DS:DGROUP

;code goes here

_TEXT   ENDS

maybe you can send me a library to try

MichaelW

I didn't spend a lot of time on it, but all of my attempts to link with the Open Watcom 1.9 libraries failed, either with an unresolved external error, or if I got past that:

fatal error L1123: _DATA : segment defined both 16- and 32-bit

I tried multiple different libraries, for example those in C:\WATCOM\LIB386\DOS and C:\WATCOM\LIB386\WIN (AFAIK these are Win16 libraries). I have doubts that the libraries are compatible with the Microsoft tools.
eschew obfuscation

allynm

Hi DednDAve and MichaelW

I tried 'Dave's suggestion, but got the same error message after swapping out _CODE with _TEXT.  Namely, _TEXT : segment size exceeds 64K.   

I'm basically where MichaelW is on Watcom.  Watcom's documentation on its libraries is pretty good.  They created different libs for c functions that depended on the model size specified in the source code.  In my case they are all located in c:\watcom\lib286\dos. Watcom named its files clibs.lib, clibm.lib, and clibl.lib.  Following MichaelW's suggestion my caller is defined as .MODEL large, c and I have been trying to link with Watcom's clibl.lib. 

DednDave:  I will send you a copy of clibl.lib later today.

Regards,
Mark


dedndave

ok - i would have started with a small model program
small - all code fits into a single segment, all data fits into a single segment
for these trivials, large is a bit much - lol
large indicates multiple code and multiple data segments
as i recall, medium indicates a single code segment and multiple data segments

the error sounds something more like some kind of syntax problem
you are somehow not meeting the requirements of the LIB and/or LINK
or, perhaps, you are calling every c function in the lib - lol

MichaelW

Well, I didn't try the libraries in \LIB286\DOS (a 286 is not sexy enough for a young man like me). But now that I have, with a little creative guesswork I was able to get CLIBL.LIB to work. The SYSCALL for the langtype field in the PROTO and PROC directives is to eliminate the leading underscore, and because it also eliminates caller stack cleanup I added a test to verify that the called function is removing the arguments from the stack. And "printf_" would link OK, but it would not display anything. And for the commented statement, I don't know whether the problem is a bad format string or no printf support for floats (tried REAL4 and REAL8).

Edit: Just looked at the listing, and ML is adding code to remove the arguments from the stack, so my impression that ML does this only for the C langtype was wrong. And the library is following the C calling convention, but not the naming convention. And if instead of invoke you push the arguments and do a call, you will need to add code to remove the arguments from the stack on return.

;====================================================================
.model large, c
.386

;====================================================================

cprintf_  PROTO FAR SYSCALL :VARARG
rand_     PROTO FAR SYSCALL
getch_    PROTO FAR SYSCALL

;====================================================================

.stack
.data
    fmtd  db "%d%c",0
    fmth  db "%xh%c",0
    fmtf  db "%f%c",0
    r8    REAL8 123.456
.code

;====================================================================

;-------------------------------------------------------------
; This dummy procedure prevents the linker from returning an
; "unresolved external" error. Something in the library code
; is apparently referencing this name, and while the dummy
; procedure will satisfy the linker, if the library were to
; actually call the procedure it would probably fail.
;-------------------------------------------------------------

main_ proc far SYSCALL
    ret
main_ endp

.startup

;====================================================================

    ;----------------------------------------------------------------
    ; This code is to verify the the library functions do not expect
    ; caller stack cleanup, as per the C calling convention
    ;----------------------------------------------------------------

    mov dx, sp
    invoke cprintf_, ADDR fmtd, dx, 10
    mov dx, sp
    invoke cprintf_, ADDR fmtd, dx, 10


    REPEAT 10
      invoke rand_
      invoke cprintf_, ADDR fmtd, ax, 10
    ENDM

    invoke cprintf_, ADDR fmth, 1234h, 10
    mov ax, 1234h
    invoke cprintf_, ADDR fmth, ax, 10

    ;invoke cprintf_, ADDR fmtf, r8, 10

    invoke getch_

;====================================================================

.exit
end


And I could not get CLIBS.LIB to work even though I changed the model directive to match, the display was corrupted.
eschew obfuscation

FORTRANS

Hi,

   Not sure this is relevant, but some libraries need to be
initialized before using certain functions.  The Microsoft
FORTRAN library needed a start up call of some sort.
That was a somewhat unsuccessful attempt to use
the FPU emulation way back when.  You might look at
an assembly listing of a C program to see if there is
something like that required for the Watcom library?

HTH,

Steve N.

dedndave

i gave a quick browse to the watcom documentation
there appears to be no general init function
however, there are a few specialized init functions for specific things like graphics, allocation, etc

i did find several DOS/ASM source files
http://www.openwatcom.org/index.php/Resources#ASM.2FDOS_source

i would think something in there should get you up and running

1) make sure you are using the correct library for 16-bit DOS
2) the segment order may be a problem - refer to the docs
because you are not using the watcom assembler and linker, you may have to explicitly
open and close the segments in an asm inc file so that the segments are ordered correctly
i can see how this might cause the "_TEXT segment exceeds 64 kb" error
a good reason to start with the small model   :bg
http://www.openwatcom.org/index.php/Manuals
the Programmer's Guide and Tools User's Guide look like they contain a lot of good info  :P

dedndave

one more thought....
if i was in this predicament, i might compile a small dos program using watcom's c-compiler
then, tear it apart with exemod, exehdr, debug to see how it went together   :bg
i am not a c programmer, nor do i want to become one - lol

but, if you send me a small 16-bit dos exe, i can take it apart   :P

allynm

Hello SteveN, MichaelW, and DednDave,

While you folks were sending me your good ideas, I threw up my hands on Watcom and went off and downloaded some very old code written in the early 90's by Randall Hyde.  I suppose you probably know that Randall H. and UCR developed a library of c-like calls coded in asm and distributed as UCR STDLIB.  They had built a library and also included in their distribution the source files.  Many familiar faces such as the astoundingly popular printf, but also malloc and others.  I could not get my asm source to link to their library.  However, I was able to assemble and link to individual obj files built off their source code.  The code runs fine.  So, in principle it looks like I could build a static lib off their sources.  BTW, in order to get my source to link successfully I had to follow MichalW's SYSCALL langtype in the PROTO for the library procs.

Of course, the UCR/Hyde sources are not ANSI C library code.  But, it looks like for quick and dirty console I/O from DOS code compiled with ML (and of course the /omf switch) and linked from link16 (AKA link563), the UCR library will work.

I am hoping to receive tomorrow the TURBO C compiler (49 bucks!  I didn't get Redskull's note in time...) and arrive at a more elegant solution.

I will also follow up on your recent  postings.

Thanks
Mark Allyn


dedndave

we are familiar with Randy's libraries
and - if you look through the 16-bit forum, you will find many working examples

i am not sure that turbo-c 5.5 will create dos exe's - well, it does not specifically say it will
i did find an older version of turbo-c 2.01 that looks promising, however
http://cc.embarcadero.com/item/25636


allynm

Hi JJ, Dedndave, and Michael W.

I figured you folks were well acquainted with Randy Hyde, but not having seen his name mentioned here I wanted to at least indicate where I got the STDLI B stuff from.  And perhaps not everyone reading this thread knows Hyde's work...

I haven't tried out MichaelW's new code yet.  But, I did download the TurboC 2.01 files as Dave suggested.  As far as trying to understand what WATCOM is doing by writing a small program, I did that.  Their makefiles are written in a peculiar syntax and I can't see how they are actually linking in their c libs.  Dedndave's idea of tearing the thing apart is interesting but I think I'll try to make Turbo C work first. 

I looked at JJ's code.  It was highly interesting.  I stumbled for a while on what exactly was going on in the line where he loads and unloads the function--couldn't understand what the db instruction was until I reallized he had actually inserted the opcode string!  Very cool.  Because I'm pretty naive to assembly I had never seen that done.

As for what JJ's workaround does, I'm not sure it does what I'm trying to do.  All I was trying to do was simply call ANSI c functions from a DOS .exe. JJ's workaround seems to load and unload 32 bit Windows API's from a DOS .exe.  Maybe I'm missing something here.. I guess what he's driving at is that I could load and unload 32 bit C functions from msvcrt.dll/lib.  Am I right?

I certainly appreciate all the help you've given me.

Regards to all,
Mark Allyn