dillon@CORY.BERKELEY.EDU (Matt Dillon) (10/04/87)
Now could somebody post a completely working Exec Device Driver and DOS Device Driver? -Matt #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # README # hlib.asm # test.c # testlib.c # This archive created: Sat Oct 3 21:01:34 1987 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Makefile'" '(356 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \!Funky!Stuff! > 'Makefile' all: lib test lib: cc +BCDL +p +Ivd0:include/symbols.m testlib.c -o ram:testlib.o ln +Q ram:testlib.o -lcl32 copy ram:testlib libs:testlib.library delete ram:testlib ram:testlib.o test: cc +L +Ivd0:include/symbols.m test.c -o ram:test.o as hlib.asm -o ram:hlib.o ln +Q ram:test.o ram:hlib.o -lc32 delete ram:test.o !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'README'" '(2508 characters)' if test -f 'README' then echo shar: "will not over-write existing file 'README'" else cat << \!Funky!Stuff! > 'README' Working Library Skeleton for AZTEC C. By Matthew Dillon Placed in Public Domain This is an example library for Aztec C. It will not work with Lattice C due to extensive Manxisms. This library does not use the auto-init method and thus provides a contrast with the RKM example. Note especially the compile time options required (in the Makefile). Here are the reasons: +B No reference to startup code. +CD Large code and data model. Alternately you can setup A4 on every entry point and use the small code and data model. +L 32 bit integers. My preference.. not required when designing your own libraries, of course. +p compatibility option... Aztec automagically saves D2 and D3 on function calls. Otherwise we would have to do it by hand on every entry point. LINK LIBRARY: The routines in this example expect arguments on the stack. You will note the link library is incredibly simple ... the assembly to make a library call is only two instructions. Note that since the arguments are expected on the stack, the link library routines cannot save anything on the stack. A0-A1 D0-D1 are scratch however and I simply use A0. Thus this library is optimized for C->C calls. You want your library to follow the AMIGA STANDARD, which is that only A0-A1 D0-D1 may be trashed. The only register Aztec C calls will not automatically save is A6 and this must be done WITHIN your actual library routines (see testlib.c). REMEMBER: Remember that you are running in the context of the calling task inside a library call, and that the DOS library is not automatically openned for you as it is in C programs. Remember that if you use other libraries you must open them yourself, setting the proper global variable xxxxBase so the linked-in-library your run-time library uses, if any, knows what to do. E.G. the first thing my library does in the Init routine is to setup SysBase. FILES: Makefile For making the library itself. I make reference to a precompiled symbol table which is all the AMIGA includes (none of the Aztec includes) */*.h . You will have to either generate such a symbol table or simply figure out which #include's you need to make. hlib.asm Example 'link' library... what you need to link with your C programs to be able to call library functions after openning the library. testlib.c The source to the library itself. test.c The source to the test program. Must be linked with hlib.o !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'hlib.asm'" '(216 characters)' if test -f 'hlib.asm' then echo shar: "will not over-write existing file 'hlib.asm'" else cat << \!Funky!Stuff! > 'hlib.asm' ; TestBase FAR code FAR data public _TestBase public _Sub public _Add _Sub: move.l _TestBase,A0 jmp -36(A0) _Add: move.l _TestBase,A0 jmp -30(A0) !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'test.c'" '(329 characters)' if test -f 'test.c' then echo shar: "will not over-write existing file 'test.c'" else cat << \!Funky!Stuff! > 'test.c' long TestBase; extern long OpenLibrary(); extern long Add(), Sub(); main() { TestBase = OpenLibrary("testlib.library",0); if (TestBase) { printf("Open OK %08xl\n", TestBase); printf("ADD 1 -> %ld (should be 2)\n", Add(1L)); CloseLibrary(TestBase); puts("Close OK"); } else { puts("Unable to Open"); } } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'testlib.c'" '(4850 characters)' if test -f 'testlib.c' then echo shar: "will not over-write existing file 'testlib.c'" else cat << \!Funky!Stuff! > 'testlib.c' /* * TESTLIB.C * * Compile with +BCDL * +B No startup reference * +C Large code * +D Large data * +L 32 bit Integers */ #asm ; RLIB.ASM ; ; Run-time library tag FAR code FAR data public _CInit public _LibOpen public _LibClose public _LibExpunge Start: clr.l D0 rts InitDesc: dc.w $4AFC ;RTC_MATCHWORD dc.l InitDesc ;Pointer to beginning dc.l EndCode ;Note sure it matters dc.b 0 ;flags (NO RTF_AUTOINIT) dc.b 0 ;version dc.b 9 ;NT_LIBRARY dc.b 0 ;priority (doesn't matter) dc.l _Libname ;Name of library dc.l _Libid ;ID string (note CR-LF at end) dc.l Init ;Pointer to init routine _Libname: dc.b "testlib.library",0 _Libid: dc.b "testlib.library 1.0 (02 Oct 1987)",13,10,0 EndCode: Init: move.l A6,-(sp) ;Must save A6 move.l A0,-(sp) ;Segment list jsr _CInit addq.l #4,sp move.l (sp)+,A6 rts cifc macro move.l D0,-(sp) ;Make a C call and save A6 to boot move.l A6,-(sp) jsr \1 move.l (sp)+,A6 addq.l #4,sp rts endm _ALibOpen: cifc _LibOpen _ALibClose: cifc _LibClose _ALibExpunge: cifc _LibExpunge #endasm extern char Libname[1]; extern char Libid[1]; extern long ALibExpunge(),ALibClose(),ALibOpen(),ALibReserved(); extern long Lib_Add(), Lib_Sub(); /* * Function Entries consist of a JMP instruction followed by an * absolute vector. I *do* admit to cheating here... there is * an Exec call to integrate a library with a function list. I * do it all with a single static declaration. In fact, the proper * way to do it would be with MakeLibrary() especially considering * that C-A has reserved one of the library vectors. */ struct FuncList { UWORD jmp; long (*func)(); }; typedef struct Library LIB; typedef struct FuncList FLIST; struct { FLIST Funcs[6]; LIB Lib; } WLib = { 0x4EF9, Lib_Sub, 0x4EF9, Lib_Add, 0x4EF9, NULL , /* reserved by C-A? */ 0x4EF9, ALibExpunge, 0x4EF9, ALibClose , 0x4EF9, ALibOpen , { { NULL,NULL,NT_LIBRARY,0,Libname }, LIBF_CHANGED|LIBF_SUMUSED,0,sizeof(WLib.Funcs),sizeof(WLib.Lib), 0,0,(APTR)Libid,0,0 } }; long Seglist; /* Save the DOS seglist */ /* * The Initialization routine is given only a seglist pointer. Since * we are NOT AUTOINIT we must construct and add the library ourselves * and return either NULL or the library pointer. Exec has Forbid() * for us during the call. */ LIB * CInit(segment) { extern long SysBase; SysBase = *(long *)4; Seglist = segment; AddLibrary(&WLib.Lib); return(&WLib.Lib); } /* * Open is given the library pointer and the version request. Either * return the library pointer or NULL. Remove the DELAYED-EXPUNGE flag. * Exec has Forbid() for us during the call. */ LIB * LibOpen(lib,version) LIB *lib; { ++lib->lib_OpenCnt; lib->lib_Flags &= ~LIBF_DELEXP; return(lib); } /* * Close is given the library pointer and the version request. Be sure * not to decrement the open count if already zero. If the open count * is or becomes zero AND there is a LIBF_DELEXP, we expunge the library * and return the seglist. Otherwise we return NULL. * * Exec has Forbid() for us during the call. */ LibClose(lib) LIB *lib; { if (lib->lib_OpenCnt) { --lib->lib_OpenCnt; return(NULL); } if (lib->lib_Flags & LIBF_DELEXP) return(LibExpunge(lib)); return(NULL); } /* * We expunge the library and return the Seglist ONLY if the open count * is zero. If the open count is not zero we set the DELAYED-EXPUNGE * flag and return NULL. * * Exec has Forbid() for us during the call. NOTE ALSO that Expunge * might be called from the memory allocator and thus we CANNOT DO A * Wait() or otherwise take a long time to complete (straight from RKM). */ LibExpunge(lib) LIB *lib; { if (lib->lib_OpenCnt) { lib->lib_Flags |= LIBF_DELEXP; return(NULL); } Remove(lib); return(Seglist); } /* * The Library routines themselves. Note that we must also save A6 if * any library routine makes a library call to another library. These * examples do not and thus you can remove the #asm statements in them if * you wish... just DON'T FORGET! * * The reason A6 must be saved is that Aztec library interface routines * (e.g. FindTask(), OpenWindow(), etc....) trash A6 on purpose to make * the interface routine faster. */ Lib_Add(n) { #asm move.l A6,-(sp) #endasm ++n; /* do stuff here */ #asm move.l (sp)+,A6 #endasm return(n); } Lib_Sub(n) { #asm move.l A6,-(sp) #endasm --n; /* do stuff here */ #asm move.l (sp)+,A6 #endasm return(n); } !Funky!Stuff! fi # end of overwriting check exit 0 # End of shell archive
bart@amiga.UUCP (Barry A. Whitebook) (10/07/87)
[eat this line -- please!] this is amiga!bart. thanks to matt dillon for posting an example library. however, as he pointed out in his comments to the code, the system approved way of creating a library to add to the system is with the MakeLibrary call. why should YOU follow the convention of using the MakeLibrary call? well, if you are ROMCODE (or want to look like romcode, or be romcode eventually) the example as posted won't work. why would you like to look like romcode? well, for one thing there will eventually (real soon now) (actually a binary was posted recently to usenet) be a way to protect your ram-based code from reboot so that YOUR library is just like any other rom-based library as far as the system is concerned. taking the extra time and exercising the appropriate brain cells NOW will save you time later (i have got sample code to clean up and post... but currently it is at a lower priority than my "system tasks") bart -- //----------------------------------------------------- ----------\\ //| Bart Whitebook, Manager of Amiga ROM Software | {|V|))) |\\ | Comodore-Amiga, Inc. | ()^()-)))| | 16795 Lark Avenue, Suite #106, Los Gatos, CA 95030 | /_ ?))| | UUCP: pyramid!oliveb!amiga!bart | { _ } )\ | | BIX: amigabart | \ // | \\|_____________________________________________________|__\//____ |// \\ //