deven@pawl.rpi.edu (Deven Corzine) (03/03/89)
In article <92203@sun.uucp> cmcmanis%pepper@Sun.COM (Chuck McManis) writes: >In article <DEVEN.89Mar1183038@daniel.pawl.rpi.edu> shadow@pawl.rpi.edu writes: >>One question - is it possible to create a compiled C module which can >>be linked alone, without being linked to the lib:c.o startup module or >>the lib: libraries? (Clearly the libraries can be ditched if nothing >>in them is used. The question is whether or not you MUST use assembly >>for the startup module...) > >Yes, with Lattice 5.0x it is possible to have nothing but >blink myprog.o to myprog >(which sometimes you can just execute myprog.o if there are no externals >at all) > >Essentially, you will have to define your lib pointers internally and use >the prototypes for direct linkage to the libraries. Can you give me a short simple example that will work for this? Say, the classic "Hello, world!" program? I tried something like this: ----- /* hello.c */ #include <proto/exec.h> #include <proto/dos.h> struct DosLibrary *DOSBase; static char msg[]="Hello, world!\n"; void main() { DOSBase=(struct DosLibrary *) OpenLibrary("dos.library",0); Write(Output(),msg,sizeof(msg)); CloseLibrary((struct Library *) DOSBase); } ----- lc -b -r -v hello.c blink hello.o to hello smallcode smalldata (I'm trying to make the executable as small as possible, but without using assembly.) It compiled and linked without errors, with an executable size of about 100 bytes. But every time I ran it, it caused a GURU. Often GOMF didn't manage to catch it, either. I also tried moving the DOSBase and msg declarations to the end of the file and declaring them as externs in main(), I tried using _main(), (which gave me 604 bytes linking with lib:c.o+hello.o and lib:lc.lib) I tried declaring DOSBase as an extern, but the linker complained that it couldn't resolve _DOSBase (unless I linked with lib:lc.lib) and any time I managed to get it to compile and link, it wouldn't execute. At some point, I think I managed to get it to print something, half garbage. Oh, yes. One more thing - when I have the OpenLibrary() call in, it accesses df0: once, quickly, and then gurus. I think it half-worked (printed <garbage>, world! or something like that) when I took out the OpenLibrary() and CloseLibrary() calls. Something. Anyway, I couldn't get it to compile, link and run correctly. What am I doing wrong? Do I need to specially define the entry point? (or make the entry function the first function?) Or am I incorrently defining DOSBase? HELP! Deven -- ------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine --------------------- Cogito shadow@acm.rpi.edu 2346 15th Street Pi-Rho America ergo userfxb6@rpitsmts.bitnet Troy, NY 12180-2306 (518) 272-5847 sum... In the immortal words of Socrates: "I drank what?" ...I think.
gay%elde.epfl.ch@cunyvm.cuny.edu (David Gay) (03/05/89)
>/* hello.c */ >#include <proto/exec.h> >#include <proto/dos.h> > >struct DosLibrary *DOSBase; >static char msg[]="Hello, world!\n"; > >void main() >{ > DOSBase=(struct DosLibrary *) OpenLibrary("dos.library",0); > Write(Output(),msg,sizeof(msg)); > CloseLibrary((struct Library *) DOSBase); >} >----- >lc -b -r -v hello.c >blink hello.o to hello smallcode smalldata The problem is that A4 (which points to global data) is not initialised. 2 solutions: - compile with lc -b0 -v hello.c - add a call to geta4() at the start of main() (if you include <dos.h>, this will be expanded "inline"). >Deven >-- >------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine --------------------- >Cogito shadow@acm.rpi.edu 2346 15th Street Pi-Rho America >ergo userfxb6@rpitsmts.bitnet Troy, NY 12180-2306 (518) 272-5847 >sum... In the immortal words of Socrates: "I drank what?" ...I think. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ David Gay 6 x 9 = 42 GAY@ELDE.EPFL.CH, or GAY%ELDE.EPFL.CH@CLSEPF51.bitnet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cmcmanis%pepper@Sun.COM (Chuck McManis) (03/07/89)
In article <92203@sun.uucp> I wrote: > Yes, with Lattice 5.0x it is possible to have nothing but > blink myprog.o to myprog This is correct. > (which sometimes you can just execute myprog.o if there are no externals > at all) This is incorrect. > Essentially, you will have to define your lib pointers internally and use > the prototypes for direct linkage to the libraries. Then in a followup article shadow@pawl.rpi.edu writes: > Can you give me a short simple example that will work for this? Say, > the classic "Hello, world!" program? I tried something like this: To which I reply "Certainly" and here it is : To make this program run compile it like so : lc -v -b0 sm.c blink sm.o to sm You must use -b0 or somehow set up A4 to point to your data segment ahead of time. (Relative addressing on code still works fine) ------- /* Hello world very simply */ #include <exec/types.h> /* always useful */ #include <exec/memory.h> /* probably extraneous */ #include <libraries/dos.h> /* Defines dosname */ #include <proto/exec.h> /* Essential for inline calls */ #include <proto/dos.h> /* ditto */ ULONG **SysBase = (ULONG **) 4; /* The one "known" address */ ULONG *ExecBase; /* Needed for Exec functions */ struct DOSBase *DOSBase; /* Needed for DOS functions */ char msg[] = "Hello World\n"; /* Ye old message */ _main() { ExecBase = *SysBase; DOSBase = (struct DOSBase *)OpenLibrary(DOSNAME,0); Write(Output(), msg, sizeof(msg)); (void) CloseLibrary(DOSBase); return (0); } And the assembly that Lattice generates for this is : ------- Lattice AMIGA 68000-68020 OBJ Module Disassembler V5.00 Copyright ) 1988 Lattice Inc. All Rights Reserved. Amiga Object File Loader V1.00 68000 Instruction Set EXTERNAL DEFINITIONS __main 0000-00 _SysBase 0000-01 _msg 0004-01 _ExecBase 0000-02 _DOSBase 0004-02 SECTION 00 "text" 00000050 BYTES | 0000 48 E7 30 02 MOVEM.L D2-D3/A6,-(A7) | 0004 20 79 00 00 00 00-01 MOVEA.L 01.00000000,A0 | 000A 23 D0 00 00 00 00-02 MOVE.L (A0),02.00000000 | 0010 43 F9 00 00 00 12-01 LEA 01.00000012,A1 | 0016 70 00 MOVEQ #00,D0 | 0018 2C 78 00 04 MOVEA.L 0004,A6 | 001C 4E AE FD D8 JSR FDD8(A6) | 0020 23 C0 00 00 00 04-02 MOVE.L D0,02.00000004 | 0026 C1 8E EXG D0,A6 | 0028 4E AE FF C4 JSR FFC4(A6) | 002C 22 00 MOVE.L D0,D1 | 002E 41 F9 00 00 00 04-01 LEA 01.00000004,A0 | 0034 24 08 MOVE.L A0,D2 | 0036 76 0D MOVEQ #0D,D3 | 0038 4E AE FF D0 JSR FFD0(A6) | 003C 22 4E MOVEA.L A6,A1 | 003E 2C 78 00 04 MOVEA.L 0004,A6 | 0042 4E AE FE 62 JSR FE62(A6) | 0046 70 00 MOVEQ #00,D0 | 0048 4C DF 40 0C MOVEM.L (A7)+,D2-D3/A6 | 004C 4E 75 RTS SECTION 01 "data" 00000020 BYTES 0000 00 00 00 04 48 65 6C 6C 6F 20 57 6F 72 6C 64 0A ....Hello World. 0010 00 00 64 6F 73 2E 6C 69 62 72 61 72 79 00 00 00 ..dos.library... SECTION 02 "udata" 00000008 BYTES ---------- When blinked results in an executable that is 224 bytes long. You can probably trim that some. (It doesn't have to return 0). --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@sun.com These opinions are my own and no one elses, but you knew that didn't you.
deven@pawl.rpi.edu (Deven Corzine) (03/09/89)
In article <92710@sun.uucp> cmcmanis%pepper@Sun.COM (Chuck McManis) writes: >In article <92203@sun.uucp> I wrote: >To make this program run compile it like so : >lc -v -b0 sm.c >blink sm.o to sm > >You must use -b0 or somehow set up A4 to point to your data segment >ahead of time. (Relative addressing on code still works fine) > >------- >/* Hello world very simply */ >#include <exec/types.h> /* always useful */ >#include <exec/memory.h> /* probably extraneous */ >#include <libraries/dos.h> /* Defines dosname */ >#include <proto/exec.h> /* Essential for inline calls */ >#include <proto/dos.h> /* ditto */ > >ULONG **SysBase = (ULONG **) 4; /* The one "known" address */ >ULONG *ExecBase; /* Needed for Exec functions */ >struct DOSBase *DOSBase; /* Needed for DOS functions */ > >char msg[] = "Hello World\n"; /* Ye old message */ > >_main() >{ > ExecBase = *SysBase; > DOSBase = (struct DOSBase *)OpenLibrary(DOSNAME,0); > Write(Output(), msg, sizeof(msg)); > (void) CloseLibrary(DOSBase); > return (0); >} > >And the assembly that Lattice generates for this is : > >------- > >Lattice AMIGA 68000-68020 OBJ Module Disassembler V5.00 >Copyright ) 1988 Lattice Inc. All Rights Reserved. > > >Amiga Object File Loader V1.00 >68000 Instruction Set > >EXTERNAL DEFINITIONS > >__main 0000-00 _SysBase 0000-01 _msg 0004-01 _ExecBase 0000-02 >_DOSBase 0004-02 > >SECTION 00 "text" 00000050 BYTES > | 0000 48 E7 30 02 MOVEM.L D2-D3/A6,-(A7) > | 0004 20 79 00 00 00 00-01 MOVEA.L 01.00000000,A0 > | 000A 23 D0 00 00 00 00-02 MOVE.L (A0),02.00000000 > | 0010 43 F9 00 00 00 12-01 LEA 01.00000012,A1 > | 0016 70 00 MOVEQ #00,D0 > | 0018 2C 78 00 04 MOVEA.L 0004,A6 > | 001C 4E AE FD D8 JSR FDD8(A6) > | 0020 23 C0 00 00 00 04-02 MOVE.L D0,02.00000004 > | 0026 C1 8E EXG D0,A6 > | 0028 4E AE FF C4 JSR FFC4(A6) > | 002C 22 00 MOVE.L D0,D1 > | 002E 41 F9 00 00 00 04-01 LEA 01.00000004,A0 > | 0034 24 08 MOVE.L A0,D2 > | 0036 76 0D MOVEQ #0D,D3 > | 0038 4E AE FF D0 JSR FFD0(A6) > | 003C 22 4E MOVEA.L A6,A1 > | 003E 2C 78 00 04 MOVEA.L 0004,A6 > | 0042 4E AE FE 62 JSR FE62(A6) > | 0046 70 00 MOVEQ #00,D0 > | 0048 4C DF 40 0C MOVEM.L (A7)+,D2-D3/A6 > | 004C 4E 75 RTS > >SECTION 01 "data" 00000020 BYTES >0000 00 00 00 04 48 65 6C 6C 6F 20 57 6F 72 6C 64 0A ....Hello World. >0010 00 00 64 6F 73 2E 6C 69 62 72 61 72 79 00 00 00 ..dos.library... > >SECTION 02 "udata" 00000008 BYTES >---------- > >When blinked results in an executable that is 224 bytes long. You can >probably trim that some. (It doesn't have to return 0). > >--Chuck McManis >uucp: {anywhere}!sun!cmcmanis>BIX: cmcmanis ARPAnet: cmcmanis@sun.com >These opinions are my own and no one elses, but you knew that didn't you. Hmm. Well, here's what I finally got to work correctly. (The problem was indeed that A4 didn't point to the data segment) The program code: hello.c ---------- #include <proto/exec.h> #include <proto/dos.h> struct DosLibrary *DOSBase; static char msg[]="Hello, world!\n"; void main() { DOSBase=(struct DosLibrary *) OpenLibrary(DOSNAME,0); Write(Output(),msg,sizeof(msg)); CloseLibrary((struct Library *) DOSBase); } ---------- <proto/exec.h> will include <exec/types.h> if it hasn't been included yet, <proto/dos.h> will include <libraries/dosextens.h> (if it hasn't been) which will include <exec/types.h>, <exec/tasks.h>, <exec/ports.h>, <exec/libraries.h> and <libraries/dos.h>. <exec/tasks.h> will include <exec/nodes.h> and <exec/lists.h>. <exec/lists.h> will include <exec/nodes.h>. <exec/ports.h> will include <exec/nodes.h>, <exec/lists.h> and <exec/tasks.h>. <exec/libraries.h> will include <exec/nodes.h>. <libraries/dos.h> will include <exec/types.h>. Therefore, this: ---------- #include <proto/exec.h> #include <proto/dos.h> ---------- is equivalent to: ---------- #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/tasks.h> #include <exec/ports.h> #include <exec/libraries.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <proto/exec.h> #include <proto/dos.h> ---------- Compiled with: lc -b -r -v -y hello.c ---------- Lattice AmigaDOS C Compiler, Version 5.0 Copyright (C) 1988 Lattice, Inc. All rights reserved. Compiling hello.c Module size P=00000040 D=0000001C U=00000004 Total files: 1, Compiled OK: 1 ---------- (-b for base-relative addressing, -r for pc-relative branches (probably irrelevant here), -v to disable stack checking, and -y to load A4 with the data segment at the start of each function. (I forgot the -y before so it didn't work.)) Linked with: blink hello.o to hello ---------- Blink - Version 5.0 CopyRight (c) 1988 Lattice, Inc. All Rights Reserved. BLINK Complete - Maximum code size = 96 ($00000060) bytes Final output file size = 168 ($000000a8) bytes ---------- Disassembled with: omd hello.o [note: this one actually had a copyright symbol. shown here as (c).] ---------- Lattice AMIGA 68000-68020 OBJ Module Disassembler V5.00 Copyright (c) 1988 Lattice Inc. All Rights Reserved. Amiga Object File Loader V1.00 68000 Instruction Set EXTERNAL DEFINITIONS _main 0000-00 _DOSBase 0000-02 SECTION 00 "text" 00000040 BYTES | 0000 48 E7 30 0A MOVEM.L D2-D3/A4/A6,-(A7) | 0004 49 F9 00 00 00 00-XX LEA _LinkerDB,A4 | 000A 43 EC 00 10-01.2 LEA 01.00000010(A4),A1 | 000E 70 00 MOVEQ #00,D0 | 0010 2C 78 00 04 MOVEA.L 0004,A6 | 0014 4E AE FD D8 JSR FDD8(A6) | 0018 29 40 00 00-02.2 MOVE.L D0,02.00000000(A4) | 001C C1 8E EXG D0,A6 | 001E 4E AE FF C4 JSR FFC4(A6) | 0022 22 00 MOVE.L D0,D1 | 0024 41 EC 00 00-01.2 LEA 01.00000000(A4),A0 | 0028 24 08 MOVE.L A0,D2 | 002A 76 0F MOVEQ #0F,D3 | 002C 4E AE FF D0 JSR FFD0(A6) | 0030 22 4E MOVEA.L A6,A1 | 0032 2C 78 00 04 MOVEA.L 0004,A6 | 0036 4E AE FE 62 JSR FE62(A6) | 003A 4C DF 50 0C MOVEM.L (A7)+,D2-D3/A4/A6 | 003E 4E 75 RTS SECTION 01 "__MERGED" 0000001C BYTES 0000 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 0A 00 00 Hello, world!... 0010 64 6F 73 2E 6C 69 62 72 61 72 79 00 dos.library. SECTION 02 "__MERGED" 00000004 BYTES ---------- Listed with: ls -l hello* ---------- -----rwed 89-03-08 21:28:44 1 168 hello -----rwed 89-03-08 21:27:25 1 268 hello.c -----rwed 89-03-08 21:28:30 1 296 hello.o Dirs:0 Files:3 Blocks:3 Bytes:732 ---------- Ran with: hello (well, might as well be consistent...) :-) ---------- Hello, world! ---------- She works. I think 168 bytes is a pretty decent executable size, especially considering the first time I tried compiling a "Hello, world!" program, using Lattice C V3.03, (code was: "main(){printf("Hello, world!\n");}", compiled with "lc -L hello.c") the executable was on the order of about 10-11K... Actually, I left out -O on the compile command line (to run the optimizer "go" between the passes), and options nodebug (strip debugging information), smallcode (merge code hunks), and smalldata (merge data hunks) to blink. In this example, none of these change either the object file or the executable. In summary, it seems that compiling with: lc -b -r -v -y file.c and linking with: blink file.o to file nodebug smallcode smalldata will get about the smallest executable possible without modifying the code. (when using prototypes, defining lib pointers, etc.) Gee, maybe I ought to post an article on "how to be verbose"... :-) Deven -- ------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine --------------------- Cogito shadow@acm.rpi.edu 2346 15th Street Pi-Rho America ergo userfxb6@rpitsmts.bitnet Troy, NY 12180-2306 (518) 272-5847 sum... In the immortal words of Socrates: "I drank what?" ...I think.
toebes@sas.UUCP (John Toebes) (03/17/89)
In article <92710@sun.uucp> cmcmanis@sun.UUCP (Chuck McManis) writes: >In article <92203@sun.uucp> I wrote: >> Yes, with Lattice 5.0x it is possible to have nothing but >> blink myprog.o to myprog >This is correct. >> Essentially, you will have to define your lib pointers internally and use >> the prototypes for direct linkage to the libraries. > >Then in a followup article shadow@pawl.rpi.edu writes: >> Can you give me a short simple example that will work for this? Say, >> the classic "Hello, world!" program? I tried something like this: > >To which I reply "Certainly" and here it is : > ... example deleted ... Actually this question has come up quite frequently and there turns out to be an even smaller solution that is made possible with 5.0 that has the additional advantage of being RESIDENTABLE! #include <exec/types.h> #include <proto/exec.h> #include <proto/dos.h> #include <strings.h> #define MSG(f,s) Write(f,s,strlen(s)) void tinyhello() { struct DosLibrary *DOSBase; /* NOTE it is a local variable */ if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0)) != NULL) { MSG(Output(), "Hello World\n"); CloseLibrary((struct Library *)DOSBase); } } Compile this with LC -cs -v tinyhello blink tinyhello.o Note that if you use the -cs option, the strings will be put into the code section automatically. Since the library base for the call is a local variable (a trick added under 5.0) and the strings are accessed pc-relative, there is no need to have A4 set up. This trick is used in POPCLI 4 and also in the Avail program on the Lattice diskettes. Enjoy. >--Chuck McManis >uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@sun.com >These opinions are my own and no one elses, but you knew that didn't you.