Article View: comp.sys.amiga.tech
Article #9351Re: how to write reentrant C code?
From: Jeff Kelley
Date: Sun, 24 Jul 1988 19:22
Date: Sun, 24 Jul 1988 19:22
269 lines
7904 bytes
7904 bytes
In article <3415@s.cc.purdue.edu> ain@s.cc.purdue.edu (Patrick White) writes:
>
> For example, I know that static (global) variables are out, but are there
>any other things? (like string constants?)
>
With Lattice C 4.01, it is possible to have up to 64k of global variables
and reentrancy. Essentially, you use address register a4 as a free parameter
pass between all your functions. You just have to be careful to initialize it
correctly. Global variables are handy because the Lattice compiler will
generate code to access amiga libraries (other than Exec) with references to
the library base as a global variable. (e.g. using intuition.library involves
an access to IntuitionBase).
My technique allows string constants, but only with a bit of trickery to
put them in the code section rather than the data section.
> While we are on the subject, what about reentrant code in all the other
>languages for the Amiga.. like pascal, and assembly, and modula2, and
>Lattice C :-)?
This method will only work for Lattice C 4.01. I use it to write ROMmable
Exec devices in C (with a tiny piece of assembler glue common to all the
devices I've written). Writing Exec libraries currently requires a little
assembler for each library entry point to get parameters out of registers,
but if the "#pragma libcall" feature of Lattice would support passing
arguments to libraries on the stack, even this wouldn't be necessary.
Anyway, I've deviated from the topic at hand. Here's a shar file which
explains the technique and contains a demo 'Hello, world' program.
--
Jeff Kelley Graphics Lab, Dept. of Computer Science, University of Waterloo
uunet!watmath!watcgl!jvkelley tel: (519) 578-4514
"Remember, this is not a competition, only an exhibition. Please, no wagering."
- David Letterman
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by watcgl!jvkelley on Sun Jul 24 14:42:26 EDT 1988
# Contents: README data.c datatocode.c hw.c makefile startup.asm strings.c
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
Here's a simple example showing how to create a Lattice C 4.01 load file with
no data or bss sections. The global variable section, pointed to by register
a4, is dynamically allocated. Note that this only works with the small data
model and limits the combined size of globals to 64k.
The technique involved requires that all global variable declarations be
placed in one file, and referenced as 'extern's in other files where they
are used. It is not possible to statically initialize these variables,
although they may be assumed to be zero if you clear the memory dynamically
allocated for them.
The trick involves the use of what is either a bug or a feature of 'blink'.
It seems that if you have only one bss section in one of the object files,
and no data sections in any of them, then the bss section will not appear
in the load file. References to the bss section will be resolved as if it
existed, however, and this allows one to dynamically allocate it.
Note that if even a single data section is present during linking, the
linking will either fail or produce an unwanted resultant load file.
I suggest linking first with the 'PRELINK' option to 'blink', and 'omd'ing
this file to ensure that no data or bss sections are present.
It is also important to realize that strings are placed in the data section.
It is possible to put them in the code section by declaring them in a separate
file, changing the data section of the object produced by that file to a code
section, and referencing the strings as external functions. (Very gross.)
I've written a data hunk to code hunk translator to assist with this operation.
(source in datatocode.c)
Many library routines (in lc.lib and amiga.lib, for example) have data sections
and are thus off limits.
Anyway, included herein is a 'hello, world' demo of the technique.
--
Jeff Kelley Graphics Lab, Dept. of Computer Science, University of Waterloo
uunet!watmath!watcgl!jvkelley tel: (519) 578-4514
"Remember, this is not a competition, only an exhibition. Please, no wagering."
- David Letterman
@//E*O*F README//
chmod u=rw,g=r,o=r README
echo x - data.c
sed 's/^@//' > "data.c" <<'@//E*O*F data.c//'
unsigned long DOSBase;
@//E*O*F data.c//
chmod u=rw,g=r,o=r data.c
echo x - datatocode.c
sed 's/^@//' > "datatocode.c" <<'@//E*O*F datatocode.c//'
#include <stdio.h>
#define HUNK_DATA 0x3EAL
#define HUNK_CODE 0x3E9L
#define HUNK_BSS 0x3EBL
void
main(argc, argv)
int argc;
char *argv[];
{
FILE *pf;
unsigned long i;
char *name;
if (argc < 2 || argc > 3)
{
puts("Usage: dc [-z] <file>");
exit(1);
}
if (argc == 3)
{
if (strcmp(argv[1],"-z"))
{
puts("Bad option");
exit(1);
}
name = argv[2];
}
else
name = argv[1];
if (!(pf = fopen(name, "r+")))
{
puts("Can't open file");
exit(1);
}
while (fread((char *)&i, sizeof(i), 1, pf) == 1)
{
if (argc == 2)
{
if (i == HUNK_DATA)
{
fseek(pf,-sizeof(i),1);
i = HUNK_CODE;
fwrite((char *)&i,sizeof(i),1,pf);
break;
}
}
else
{
if (i == HUNK_BSS)
{
i = 0;
fseek(pf,0,1);
fwrite((char *)&i,sizeof(i),1,pf);
break;
}
}
}
fclose(pf);
}
@//E*O*F datatocode.c//
chmod u=rw,g=r,o=r datatocode.c
echo x - hw.c
sed 's/^@//' > "hw.c" <<'@//E*O*F hw.c//'
#include <exec/types.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
extern struct DosLibrary *DOSBase;
extern char *HelloWorld();
extern char *DosName();
void
myputs(s)
char *s;
{
Write(Output(), s, strlen(s));
}
void
main()
{
DOSBase = (struct DosLibrary *)OpenLibrary((char *)DosName,0);
myputs(HelloWorld);
CloseLibrary((struct Library *)DOSBase);
}
@//E*O*F hw.c//
chmod u=rw,g=r,o=r hw.c
echo x - makefile
sed 's/^@//' > "makefile" <<'@//E*O*F makefile//'
LN = blink
CC = lc
CFLAGS = -v -d
AS = asm
all: datatocode hw
datatocode: datatocode.o
$(CC) $(CFLAGS) -L datatocode.c
hw: hw.pre
$(LN) from hw.pre to hw NODEBUG
hw.pre: hw.o data.o strings.o startup.o
$(LN) from startup.o hw.o data.o strings.o to hw.pre lib lib:lc.lib PRELINK SMALLCODE SMALLDATA
hw.o: hw.c
$(CC) $(CFLAGS) hw.c
data.o: data.c
$(CC) $(CFLAGS) data.c
strings.o: strings.c
$(CC) -v -b0 strings.c
datatocode strings.o
startup.o: startup.asm
$(AS) startup.asm
@//E*O*F makefile//
chmod u=rw,g=r,o=r makefile
echo x - startup.asm
sed 's/^@//' > "startup.asm" <<'@//E*O*F startup.asm//'
SECTION startup,CODE
XREF _main
ABSEXECBASE EQU 4
DATASIZE EQU 4
move.l ABSEXECBASE.w,a6
move.l #DATASIZE,d0
moveq.l #0,d1
jsr -$00c6(a6) AllocMem
tst.l d0
beq nomem
movea.l d0,a4 Set up base register
jsr _main
move.l ABSEXECBASE.w,a6
movea.l a4,a1
move.l #DATASIZE,d0
jsr -$00d2(a6) FreeMem
nomem:
rts
END
@//E*O*F startup.asm//
chmod u=rw,g=r,o=r startup.asm
echo x - strings.c
sed 's/^@//' > "strings.c" <<'@//E*O*F strings.c//'
char HelloWorld[] = "Hello, world.\n";
char DosName[] = "dos.library";
@//E*O*F strings.c//
chmod u=rw,g=r,o=r strings.c
exit 0
Technical Details
Message-ID:
<5283@watcgl.waterloo.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!watcgl!jvkelleyReferences:
<3415@s.cc.purdue.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!watcgl!jvkelley From: jvkelley@watcgl.waterloo.edu (Jeff Kelley) Newsgroups: comp.sys.amiga.tech Subject: Re: how to write reentrant C code? Keywords: reentrant, code Message-ID: <5283@watcgl.waterloo.edu> Date: 24 Jul 88 19:22:21 GMT References: <3415@s.cc.purdue.edu> Reply-To: jvkelley@watcgl.waterloo.edu (Jeff Kelley) Organization: U. of Waterloo, Ontario Lines: 269