[comp.sys.amiga.tech] Writing small code in SAS/C 5.10

lord@leadsv.UUCP (Parker Lord) (09/27/90)

I wrote myself a unix like 'mv' command because the AmigaDOS rename seemed
to limited.  My problem is that the linked code comes out to be about 9K.
I used the SD SC ND flags with Blink.  I thought that this was rather large
for the amount of code actually written so I tried a test.  I wrote a one line
program that does nothing more than a printf("Hello\n");  I compiled and linked
this using lc -L.  This code came out at about 4.6K.  In comparison, the
AmigaDOS rename command is less than 1K and the ARP mv command is about 1K.
Are there some general guidelines to follow to make linked code smaller?  
I also invoked the global optimizer with lc, but that didn't help at all.
+--------------------------------------------------------------------------+
|                                   //     AA   M     M I GGGGGG    AA     |
|     Parker J. Lord               //     A  A  MM   MM   G        A  A    |
|     lord@leadsv.UUCP            //     A    A M M M M I G       A    A   |
|     415-326-7539          \\   //      AAAAAA M  M  M I G   GGG AAAAAA   |
|                            \\ //       A    A M     M I G    G  A    A   |
|                             \\/        A    A M     M I GGGGGG  A    A   |
+--------------------------------------------------------------------------+

jmeissen@ogicse.ogi.edu (John Meissen) (09/29/90)

In article <13148@leadsv.UUCP> lord@leadsv.UUCP (Parker Lord) writes:
>I wrote myself a unix like 'mv' command because the AmigaDOS rename seemed
>to limited.  My problem is that the linked code comes out to be about 9K.
>I used the SD SC ND flags with Blink.  I thought that this was rather large
>for the amount of code actually written so I tried a test.  I wrote a one line
>program that does nothing more than a printf("Hello\n");  I compiled and linked
>this using lc -L.  This code came out at about 4.6K.  In comparison, the
>AmigaDOS rename command is less than 1K and the ARP mv command is about 1K.
>Are there some general guidelines to follow to make linked code smaller?  
>I also invoked the global optimizer with lc, but that didn't help at all.

Aaaack! This is one of my pet peeves! Does anybody out there have ANY idea
how much work printf() does and how large it is? If you want to write the
largest program possible for printing a string, use printf()! Please,
please, please don't use printf() for size comparisons.

The reasons for the large code size are 1.convenience, 2.unix compatibility,
and 3.library code.

By DEFAULT, you have buffered file I/O for stdin, stdout, and stderr set up
for you. THere's also code that will open a console window if you're 
running under Workbench. There's code that sets up the run-time environment
(stack, arguments, whatever), tracks memory allocation and file usage (Unix
style).

The secret is to use the MAP option of blink. Look at where the memory
is going, figure out what's being called and why, and then figure out a
different way of doing things that doesn't have that effect. Also, check
out c.a and umain.c.

If you can, get a copy of the NagRag from December 1989 and Jan-Feb 1990
(Newsletter of the Northwest Amiga Group, P.O. Box 1140, Oregon City, OR
97045). I wrote a 3-part series on how to trim the excess from your Lattice
C programs.


-- 
John Meissen .............................. Oregon Advanced Computing Institute
jmeissen@oacis.org        (Internet) | "That's the remarkable thing about life;
..!sequent!oacis!jmeissen (UUCP)     |  things are never so bad that they can't
jmeissen                  (BIX)      |  get worse." - Calvin & Hobbes

labb-2ae@e260-2d.berkeley.edu (Joe C.) (09/30/90)

In article <12482@ogicse.ogi.edu> jmeissen@ogicse.ogi.edu (John Meissen) writes:
>In article <13148@leadsv.UUCP> lord@leadsv.UUCP (Parker Lord) writes:
[deleted]
>>program that does nothing more than a printf("Hello\n");  I compiled and linked
>>this using lc -L.  This code came out at about 4.6K.  In comparison, the
>[deleted]
>Aaaack! This is one of my pet peeves! Does anybody out there have ANY idea
>how much work printf() does and how large it is? If you want to write the
>largest program possible for printing a string, use printf()! Please,
>please, please don't use printf() for size comparisons.

Lattice (or is that SAS/C) has three different versions of printf().  If you
include <stdio.h> in the beginning, then the compiler will use
	_writes() if you only have a string.
	_tinyprintf() if all you have is %s,%s or %p.

This can result in a saving of > 2K in final code size.

Also, the main program itself is not the culprit, it is the linking process
that increases your size.

If you tried:
#include <stdio.h>
{ printf("Hello\n"); }

An compiled with lc -Lncd -O -v

Then the assembly output would be roughly

PEA       01.00000000(A4)
JSR       __writes(PC)
ADDQW    #4,A7
RTS

But if you look at the map file of the linker, it brings in lc.lib and uses
about 40 functions in there.

-jc

UH2@psuvm.psu.edu (Lee Sailer) (09/30/90)

>Also, the main program itself is not the culprit, it is the linking process
>that increases your size.


Another thing that increases the final code size, at least in Lattice 4.01,
is the "startup code."  Before your main() gets executed, a program called
_main() is executed.  It is moderately large.

_main() sets up the WorkBench message port, parses the command line, and
other stuff like that.  You probably don't need it all.  You can find the
source to _main(), edit out the parts yopu don't need, and use it instead
of the general purpose original.
                                lee

guineau@wjg.enet.dec.com (W. John Guineau) (10/01/90)

In article <90273.111443UH2@psuvm.psu.edu>, UH2@psuvm.psu.edu (Lee Sailer)
writes:
|> From: UH2@psuvm.psu.edu (Lee Sailer)
|> Newsgroups: comp.sys.amiga.tech
|> Subject: Re: Writing small code in SAS/C 5.10
|> 
|> 
|> >Also, the main program itself is not the culprit, it is the linking process
|> >that increases your size.
|> 
|> 
|> Another thing that increases the final code size, at least in Lattice 4.01,
|> is the "startup code."  Before your main() gets executed, a program called
|> _main() is executed.  It is moderately large.
|> 
|> _main() sets up the WorkBench message port, parses the command line, and
|> other stuff like that.  You probably don't need it all.  You can find the
|> source to _main(), edit out the parts yopu don't need, and use it instead
|> of the general purpose original.
|>                                 lee
|> 

I've needed to hack up c.a a few times, and was wondering if it's was
legal to include the modified source (called myc.a or something) with
PD distributions which include source?

--
W. John Guineau   			guineau@wjg.enet.dec.com
Digital Equipment Corporation
Marlboro MA. 01752

walker@unx.sas.com (Doug Walker) (10/02/90)

In article <13148@leadsv.UUCP> lord@leadsv.UUCP (Parker Lord) writes:
>I wrote myself a unix like 'mv' command because the AmigaDOS rename seemed
>to limited.  My problem is that the linked code comes out to be about 9K.
>I used the SD SC ND flags with Blink.  I thought that this was rather large
>for the amount of code actually written so I tried a test.  I wrote a one line
>program that does nothing more than a printf("Hello\n");  I compiled and linked
>this using lc -L.  This code came out at about 4.6K.  In comparison, the
>AmigaDOS rename command is less than 1K and the ARP mv command is about 1K.
>Are there some general guidelines to follow to make linked code smaller?  
>I also invoked the global optimizer with lc, but that didn't help at all.

If you can do without stdin/stdout/stderr, I suggest using the __tinymain
stuff in the compiler - see the manual for details.  If you want to do
even more, you can call your main routine _main instead of main and do
without almost all of the C startup - if you do this, you won't get
argc and argv as parameters, you'll get a pointer to the command line and
that's it.  Almost all of the overhead in the program you listed is due
to this overhead.  Try the following for a 132-byte program to do what
yours does:

#include <proto/exec.h>
#include <proto/dos.h>

struct DosLibrary *DOSBase;

void foo(void)
{
   DOSBase = OpenLibrary("dos.library", 0);
   Write(Output(), "Hello\n", 6);
   CloseLibrary(DOSBase);
}

Use the following to compile and link it:

lc foo
blink from foo.o to foo

Note that you don't link with c.o, and you don't link with lc.lib or
amiga.lib. 


  *****
=*|_o_o|\\=====Doug Walker, Software Distiller====== BBS: (919)460-7430 =
 *|. o.| ||
  | o  |//     For all you do, this bug's for you!
  ====== 
usenet: ...mcnc!rti!sas!walker   plink: dwalker  bix: djwalker 

jdege@ (Jeff Dege) (10/02/90)

In article <1990Oct01.212023.9242@unx.sas.com> walker@unx.sas.com (Doug Walker) writes:
> Try the following for a 132-byte program to do what
>yours does:
>
>#include <proto/exec.h>
>#include <proto/dos.h>
>
>struct DosLibrary *DOSBase;
>
>void foo(void)
>{
>   DOSBase = OpenLibrary("dos.library", 0);
>   Write(Output(), "Hello\n", 6);
>   CloseLibrary(DOSBase);
>}
>
>Use the following to compile and link it:
>
>lc foo
>blink from foo.o to foo
>
>Note that you don't link with c.o, and you don't link with lc.lib or
>amiga.lib. 
>
>
>  *****
>=*|_o_o|\\=====Doug Walker, Software Distiller====== BBS: (919)460-7430 =

   I tried it, and it didn't work.  BLINK complained about undefined names.
The solution, of course, is to turn off stack checking:  "lc -v foo".
I thought I'd mention it before folks started complaining (and it ended
up as 136 bytes ;)
 
----------------
 
??

olch@geocub.greco-prog.fr (Olivier Charrier) (10/04/90)

>Lattice (or is that SAS/C) has three different versions of printf().  If you
>include <stdio.h> in the beginning, then the compiler will use
>	_writes() if you only have a string.
>	_tinyprintf() if all you have is %s,%s or %p.
>
>This can result in a saving of > 2K in final code size.

  There is another solution to fully use the printf capabilities (well,
almost fully) with very little space: use Exec's function RawDoFmt().

  It's a bit tricky to master but I was able to use %d and %s in a program
merely less than 500 bytes long. See Amiga Programmer's Handbook for
more details.

  I think it's worth it.