Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Any compilers and linkers that will generate code that does not require an OS?

124 views
Skip to first unread message

James Harris

unread,
Jan 28, 2013, 5:08:42 AM1/28/13
to
Before an OS has been loaded a computer must run some code in order to
boot. That code cannot call on any operating system facilities though
it may have access to the BIOS.

Having always written such code in assembly where I can control what
the code does it just occurred to me to wonder whether the output of
compilers depends on a specific OS or whether there are some compilers
which will generate code which does not need an OS.

AIUI compiled code would pull in and be built with various library
facilities - such as the C library. But a lot of that library would
have to make calls to an operating system in order to work - e.g. IO
routines. Such OS routines would not be available so those library
calls would not work.

In the absence of OS-provided memory management calls such as sbrk and
similar I guess that even malloc would not be available.

Are there C libraries which make calls to the BIOS instead of to an
OS?

All I can think of is to do one of the following.

* Write C (or other HLL) code which makes no calls on standard
libraries and not link the code with any standard libraries.

* Provide own-written subroutines which manage memory and call the
BIOS as needed.

Is there a right approach? If you boot from a bare machine using some
self-written HLL code what do you guys do?

James

Simon Clubley

unread,
Jan 28, 2013, 8:02:12 AM1/28/13
to
On 2013-01-28, James Harris <james.h...@gmail.com> wrote:
> Before an OS has been loaded a computer must run some code in order to
> boot. That code cannot call on any operating system facilities though
> it may have access to the BIOS.
>
> Having always written such code in assembly where I can control what
> the code does it just occurred to me to wonder whether the output of
> compilers depends on a specific OS or whether there are some compilers
> which will generate code which does not need an OS.
>

gcc does this just fine when built as a cross compiler for a bare metal
target. I use binutils to generate the final image and supply a custom
linker script to ld to do the linking.

[Before going any further, although this is a.o.d, you should note my
experience in this area is writing bare metal code to run on embedded
processors, not general OS development. Also, my embedded targets are
mainly ARM and AVR; I don't do bare metal work on x86.]

The actual code generation part of gcc _should_ be OS independent; it's
the routines called by your code which have OS dependent attributes.

> AIUI compiled code would pull in and be built with various library
> facilities - such as the C library. But a lot of that library would
> have to make calls to an operating system in order to work - e.g. IO
> routines. Such OS routines would not be available so those library
> calls would not work.
>
> In the absence of OS-provided memory management calls such as sbrk and
> similar I guess that even malloc would not be available.
>

What you need to look at is newlib. It's designed for use on embedded
targets. See http://sourceware.org/newlib/

libc support for bare metal 8-bit AVRs is also available in the form
of avr-libc at http://www.nongnu.org/avr-libc/

However, I routinely write code in C for low end ARM boards and 8-bit MCUs
which never goes anywhere near the C library. I/O is performed using my own
library which has a higher level device independent component and a lower
level device specific component.

As well as providing me with a common API across widely different MCUs, it
also allows me to add in things like a Tx-only software UART to the AVRs
I use which is integrated with the rest of my I/O library.

(Having a extra UART on a one UART device is _very_ useful for debugging.)

> Are there C libraries which make calls to the BIOS instead of to an
> OS?
>

I don't do any bare metal embedded work on x86, so I have never had to
call the BIOS directly in at least 10 years; therefore I will leave others
to answer this.

> All I can think of is to do one of the following.
>
> * Write C (or other HLL) code which makes no calls on standard
> libraries and not link the code with any standard libraries.
>

This is the option I usually choose for my low end MCU bare metal code.
For higher end MCUs (say ARM 9 and above) I've experimented with using
RTEMS (a open source RTOS) which I've written a board specific package
for.

> * Provide own-written subroutines which manage memory and call the
> BIOS as needed.
>

This is just a re-statement of the previous option in many ways; if you
need to do memory management, writing routines to do it yourself follows
on from not using a standard library to do it for you.

> Is there a right approach? If you boot from a bare machine using some
> self-written HLL code what do you guys do?
>

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

Simon Clubley

unread,
Jan 28, 2013, 1:04:35 PM1/28/13
to
On 2013-01-28, Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
>
> The actual code generation part of gcc _should_ be OS independent; it's
> the routines called by your code which have OS dependent attributes.
>

There's one exception to this I can currently think of.

In Ada, exception support, as well as some other Ada language features,
requires run-time support which is automatically included by the compiler
and this run-time support is OS environment specific.

I cannot remember coming across anything in the C language itself (as
opposed to C's run time library) which requires that kind of OS specific
support.

gcc also generates calls to various built-ins for specific low level
functions, but I've also yet to come across anything which is OS
specific (as opposed to architecture specific).

Alexei A. Frounze

unread,
Jan 30, 2013, 6:41:41 AM1/30/13
to
Probably most C compilers can be used to generate OS-independent code
and you can substitute your own version of the standard library
relying on whatever you have, be it hardware or BIOS or both. I've
done it with Turbo C, Open Watcom C and gcc. Others have done it with
MSVC++ as well.

Alex

James Harris

unread,
Jan 30, 2013, 10:26:44 AM1/30/13
to
On Jan 28, 1:02 pm, Simon Clubley <clubley@remove_me.eisner.decus.org-
Earth.UFP> wrote:
> On 2013-01-28, James Harris <james.harri...@gmail.com> wrote:
>
> > Before an OS has been loaded a computer must run some code in order to
> > boot. That code cannot call on any operating system facilities though
> > it may have access to the BIOS.
>
> > Having always written such code in assembly where I can control what
> > the code does it just occurred to me to wonder whether the output of
> > compilers depends on a specific OS or whether there are some compilers
> > which will generate code which does not need an OS.
>
> gcc does this just fine when built as a cross compiler for a bare metal
> target. I use binutils to generate the final image and supply a custom
> linker script to ld to do the linking.

Thanks. I don't think gcc and ld will work for me in this instance as
this has to be 16-bit code and AFAICT they don't support it but it
looks like I can use some other compilers so this is good to hear.
Will say more on this in reply to Alexei.

>
> [Before going any further, although this is a.o.d, you should note my
> experience in this area is writing bare metal code to run on embedded
> processors, not general OS development. Also, my embedded targets are
> mainly ARM and AVR; I don't do bare metal work on x86.]
>
> The actual code generation part of gcc _should_ be OS independent; it's
> the routines called by your code which have OS dependent attributes.

OK

> > AIUI compiled code would pull in and be built with various library
> > facilities - such as the C library. But a lot of that library would
> > have to make calls to an operating system in order to work - e.g. IO
> > routines. Such OS routines would not be available so those library
> > calls would not work.
>
> > In the absence of OS-provided memory management calls such as sbrk and
> > similar I guess that even malloc would not be available.
>
> What you need to look at is newlib. It's designed for use on embedded
> targets. See http://sourceware.org/newlib/
>
> libc support for bare metal 8-bit AVRs is also available in the form
> of avr-libc at http://www.nongnu.org/avr-libc/

They look useful. In particular newlib looks great. There are even
example system call implementations in the link below which means it
looks like it would work with almost no programming required. Very
cool!

http://sourceware.org/newlib/libc.html#Syscalls

Or, even if I wrote the system calls myself at least the examples help
show clearly what's required.

James

James Harris

unread,
Jan 30, 2013, 11:04:13 AM1/30/13
to
On Jan 30, 11:41 am, "Alexei A. Frounze" <alexfrun...@gmail.com>
wrote:

...

> Probably most C compilers can be used to generate OS-independent code
> and you can substitute your own version of the standard library
> relying on whatever you have, be it hardware or BIOS or both. I've
> done it with Turbo C, Open Watcom C and gcc. Others have done it with
> MSVC++ as well.

Thanks. Open Watcom looks good if I can get it to behave! Have
commented on that in the other thread.

James

wolfgang kern

unread,
Feb 1, 2013, 4:34:19 PM2/1/13
to

James Harris polled for:

> Before an OS has been loaded a computer must run some code in order to
> boot. That code cannot call on any operating system facilities though
> it may have access to the BIOS.

[...]

I once (many years ago) raised this question to myself and decided to
almost ignore the few given hardware-info from BIOS and check on all
legacy-ports/PCI-config specs on my own ...

So if you want any HLL-lib to perform such a job, you may need to
write such a C-lib function into your Library-collection first.

Hardware-abstractions may be if help for HLL users, but usually end
up up in detouring bloatware and they tend to be machine-specific
anyway. So I'd recommend Low-Level-ASM for this part of OS-design.

__
wolfgang





Rod Pemberton

unread,
Feb 4, 2013, 2:40:41 AM2/4/13
to
"James Harris" <james.h...@gmail.com> wrote in message
news:134aa154-458f-4bcf...@l13g2000yqe.googlegroups.com...
> Before an OS has been loaded a computer must run
> some code in order to boot. That code cannot call on
> any operating system facilities though it may have
> access to the BIOS.
>
> Having always written such code in assembly where
> I can control what the code does it just occurred to
> me to wonder whether the output of compilers depends
> on a specific OS or whether there are some compilers
> which will generate code which does not need an OS.
>
> AIUI compiled code would pull in and be built with
> various library facilities - such as the C library. But
> a lot of that library would have to make calls to an
> operating system in order to work - e.g. IO routines.
> Such OS routines would not be available so those
> library calls would not work.
>

Generally, I consider C library character and string functions to
be independent of the OS, file I/O and directory functions to be
dependent on the OS, all print and scan functions to be dependent
on the OS except sprintf, all memory management functions to be
dependent on the OS, and all non-function based memory allocation
to be independent of the OS (auto variables, declarations, etc).
Of course, you need to confirm for each library you use. For a
simple OS like DOS, you can assume it's true until something
fails. Or, you can code your own replacement routines.

Even though that is likely true, the independence or dependence on
a host OS depends on the OS and the C library. For an OS like
Windows or Linux, a well developed C library will make many, many
calls to the host OS, likely for nearly everything. For mostly
independent C libraries, like Redhat's newlib or PJ Plauger's C
library in his book: "The Strandard C Library", these only need 18
to 20 host OS functions to call.

I listed them in this post:
https://groups.google.com/group/alt.os.development/msg/f24d9ecc3f242c38

Do you remember it?

> In the absence of OS-provided memory management calls
> such as sbrk and similar I guess that even malloc would
> not be available.
>
> Are there C libraries which make calls to the BIOS
> instead of to an OS?
>

AFAIK, all C libraries call an OS. The smallest number of needed
functions I've seen are listed in the post above.

Typically, non-DOS C libraries won't call the BIOS. They'll call
the host OS exclusively.

However, DOS C libraries call the BIOS and DOS. I.e., they'll do
half of what you want and half of what you don't. Of course, it'd
probably be easier to start with newlib and backfill the 18 to 20
functions with code from DJGPP custom C library or your own ...

It's possible that there might've been or might still be some C
library that was written for just BIOS calls, but I'm not aware of
it. I'd suspect if it exists or existed that it'd be for embedded
x86 PC work.

> All I can think of is to do one of the following.
>
> * Write C (or other HLL) code which makes no calls on
> standard libraries and not link the code with any standard
> libraries.
>
> * Provide own-written subroutines which manage memory
> and call the BIOS as needed.
>

Yes, writing a kernel C library, is a standard approach. E.g.,

Luca Abeni "OSLib" http://oslib.sourceforge.net/

Or, others:

Luigi Srgo "Kernel Toolkit"
http://web.archive.org/web/20060703220210/http://web.tiscali.it/luigisgro/ktk.html

Flux OS Toolkit
http://www.cs.utah.edu/flux/oskit/

> Is there a right approach? If you boot from a bare machine using
> some self-written HLL code what do you guys do?
>

I was working on getting my OS to start with Multiboot, e.g.,
GRUB, so that I wouldn't have to have some "self-written HLL code"
to "boot from a bare machine" ...


Rod Pemberton



James Harris

unread,
Feb 15, 2013, 4:57:09 PM2/15/13
to
Up til now I have written a fair bit of 16-bit code in assembly
possibly because I was mainly accessing device registers. I would
still choose assembly for that every time. Such code is much easier to
do in asm.

Here, though, the code I want to write will involve more data
manipulation - sorting and searching and similar - and more human
interaction. I also want it to be extensible and to make it easy for
others to change if they wish to. A HLL therefore seems to be a better
choice for at least some of this code. Some asm will still be needed.

I agree with your point, though. I may go back to assembly and provide
a number of callable functions for common uses.

James

James Harris

unread,
Mar 2, 2013, 4:20:09 AM3/2/13
to
On Jan 30, 3:26 pm, James Harris <james.harri...@gmail.com> wrote:

...

> > What you need to look at is newlib. It's designed for use on embedded
> > targets. See http://sourceware.org/newlib/
>
> > libc support for bare metal 8-bit AVRs is also available in the form
> > of avr-libc at http://www.nongnu.org/avr-libc/
>
> They look useful. In particular newlib looks great.

I tried using C libraries. As far as I could see, though, they are
largely an all-or-nothing solution. In other words they expect to be
compiled as a unit and form a single object file.

I wanted only a few routines. I know in theory that I could have
copied the sources for just the functions I needed but some of them
have dependencies. Too, the sources I saw had loads of #ifdef
conditional compilation which I didn't want.

So I ended up writing the routines I needed so far. There were only a
few of them. They are generally assembler interfaces with the BIOS to
allow C code to call BIOS routines. So far only one routine is purely
in C. It is the printf formatting routine - essentially sprintf. It
parses all the format specifications but I have only added the actual
formatting routines - integers, hex, chars, strings, padding and
alignment - as I needed them. Notwithstanding the current routines
limitations writing it was easier than I anticipated. And because it
does not depend on any other C library routines it is self contained.

As a bit of an aside I am not sure that sprintf is a good idea in the
long run. For example, to format a 4-byte unsigned integer on a 16-bit
machine seems to require a format specification change from %u to %lu.
The problem with that is that %lu will be wrong for the same value if
compiled on a 32-bit machine. I believe C99 provides workarounds but
they are cumbersome/ugly and I am not sure well supported on 16-bit
compilers.

All-in-all the code development is progressing. The program can be run
under MS-DOS but does not use MS-DOS. I haven't written the exe loader
for it yet but it should run just on the BIOS as it only makes BIOS
calls.

Thanks for all the help from you guys in this and the related threads.

James

Alexei A. Frounze

unread,
Mar 3, 2013, 4:44:07 AM3/3/13
to
On Mar 2, 1:20 am, James Harris <james.harri...@gmail.com> wrote:
...
> As a bit of an aside I am not sure that sprintf is a good idea in the
> long run. For example, to format a 4-byte unsigned integer on a 16-bit
> machine seems to require a format specification change from %u to %lu.
> The problem with that is that %lu will be wrong for the same value if
> compiled on a 32-bit machine. I believe C99 provides workarounds but
> they are cumbersome/ugly and I am not sure well supported on 16-bit
> compilers.

[unsigned] long has at least 32 bits, starting with C89. It's 32-bit
in Turbo/Borland C/C++ (16/32 DOS/Windows versions), Open Watcom C/C++
(16/32 DOS/Windows versions), DGJPP gcc/g++, MinGW gcc/g++ and
Microsoft Visual C/C++ (Windows version, at least).

What you can do if you need a 32-bit type, but your compiler does not
support uint32_t and the like is something like this:

#include <limits.h>
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned uint32;
#else
typedef unsigned long uint32;
#endif

And then you could also define a few string literals for formatting:

#include <limits.h>
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned uint32;
#define PRI32u "u"
#define PRI32X "X"
#else
typedef unsigned long uint32;
#define PRI32u "lu"
#define PRI32X "lX"
#endif

and then do:

uint32 blah = 42;
printf("blah = %" PRI32u "\n", blah);

You get the idea.

There are similar string literals defined in C99, but your compiler
may not support them.

You can throw in some compile-time asserts to ensure that the
typedef'ed types have the right size:

#include <limits.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);

These can also help ensure the right size of structures and offsets of
their members.

> All-in-all the code development is progressing. The program can be run
> under MS-DOS but does not use MS-DOS. I haven't written the exe loader
> for it yet but it should run just on the BIOS as it only makes BIOS
> calls.

Cool!

Alex

Rod Pemberton

unread,
Mar 3, 2013, 3:25:00 PM3/3/13
to
"James Harris" <james.h...@gmail.com> wrote in message
news:d66564b7-b531-48ed...@he10g2000vbb.googlegroups.com...
> On Jan 30, 3:26 pm, James Harris <james.harri...@gmail.com>
wrote:

...

> > > What you need to look at is newlib. It's designed for
> > > use on embedded targets.
> > > See http://sourceware.org/newlib/
> > >
> > > libc support for bare metal 8-bit AVRs is also available in
> > > the form of avr-libc at http://www.nongnu.org/avr-libc/
>
> > They look useful. In particular newlib looks great.
>
> I tried using C libraries. As far as I could see, though, they
> are largely an all-or-nothing solution. In other words they
> expect to be compiled as a unit and form a single object file.

That's too bad. I would've thought they were independent.

> I wanted only a few routines. I know in theory that I could have
> copied the sources for just the functions I needed but some of
> them have dependencies. Too, the sources I saw had loads of
> #ifdef conditional compilation which I didn't want.

I'll take it that it's far more than just a C++ wrapper or just an
check to see if the file was included already.

I might've recommended a smaller, simpler C library or a kernel
library, maybe Paul Edward's PDPCLIB or Luca Abeni's OSLib.

> So I ended up writing the routines I needed so far. There were
> only a few of them. They are generally assembler interfaces with
> the BIOS to allow C code to call BIOS routines. So far only one
> routine is purely in C. It is the printf formatting routine -
> essentially sprintf. It parses all the format specifications
> but I have only added the actual formatting routines - integers,
> hex, chars, strings, padding and alignment - as I needed them.
> Notwithstanding the current routine[']s limitations writing
> it was easier than I anticipated. And because it does not depend
> on any other C library routines it is self contained.

Good job!

> As a bit of an aside I am not sure that sprintf is a good idea
> in the long run.

Yeah ... probably not, but it's the "C-way". I think I only use
two maybe three formats with sprintf() in my kernel. If
attempting to eliminate it, I'd probably break it into separate
custom routines. I generally prefer to use hexadecimal. It's
easy to convert integers to hex in C.

It's easy to change sprintf() to something more safe or set it up
to use a kernel function instead, if your C compiler has a
pre-processor. E.g., I sometimes need a modified printf(), e.g.,
for indentation, or a printf() function local to my application.
What I do in that case is use a similar name, so people have an
idea of what it is, and then have #defines to selectively set it
to a standard C libary function or to my custom function.

#if 1
#define LOCAL
#endif

#ifndef LOCAL
#include <stdio.h>
#define l_printf printf
#endif

...
l_printf("...blah...\n");
...

> For example, to format a 4-byte unsigned integer on a 16-bit
> machine seems to require a format specification change from
> %u to %lu. The problem with that is that %lu will be wrong
> for the same value if compiled on a 32-bit machine. I believe
> C99 provides workarounds but they are cumbersome/ugly
> and I am not sure well supported on 16-bit compilers.

The printf() sizes are going to be relative to the host machine's
sizes. Some of the larger printf() sizes are not standardized,
but frequently used. Unix and POSIX environments frequently have
and use a bunch that are not ANSI/ISO C/C++. I wouldn't expect a
16-bit compiler to support any integer size above 16-bits. I.e.,
I'd only expect machine native integer size. Although, many
16-bit compilers do seem to support using two 16-bit words as a
32-bit integer. I definately wouldn't expect 64-bits in a 16-bit
compiler.

> All-in-all the code development is progressing. The program
> can be run under MS-DOS but does not use MS-DOS. I haven't
> written the exe loader for it yet but it should run just on the
> BIOS as it only makes BIOS calls.

Great job!


Rod Pemberton






Rod Pemberton

unread,
Mar 3, 2013, 3:25:34 PM3/3/13
to
"Alexei A. Frounze" <alexf...@gmail.com> wrote in message
news:c5cde60c-120f-4586...@i5g2000pbj.googlegroups.com...
On Mar 2, 1:20 am, James Harris <james.harri...@gmail.com> wrote:
...
> > As a bit of an aside I am not sure that sprintf is a good idea
> > in the long run. For example, to format a 4-byte unsigned
> > integer on a 16-bit machine seems to require a format
> > specification change from %u to %lu. The problem with
> > that is that %lu will be wrong for the same value if
> > compiled on a 32-bit machine. I believe C99 provides
> > workarounds but they are cumbersome/ugly and I am
> > not sure well supported on 16-bit compilers.
>
> [unsigned] long has at least 32 bits, starting with C89. It's
> 32-bit in Turbo/Borland C/C++ (16/32 DOS/Windows
> versions), Open Watcom C/C++ (16/32 DOS/Windows
> versions), DGJPP gcc/g++, MinGW gcc/g++ and
> Microsoft Visual C/C++ (Windows version, at least).

Well, that's good to know. I generally don't assume anything over
the machine's native integer size is available, although many C
compilers seemed support twice that.

> What you can do if you need a 32-bit type, but your compiler
> does not support uint32_t and the like is something like this:
>
> #include <limits.h>
> #if UINT_MAX >= 0xFFFFFFFF
> typedef unsigned uint32;
> #else
> typedef unsigned long uint32;
> #endif
>
> And then you could also define a few string literals for
> formatting:
>
> #include <limits.h>
> #if UINT_MAX >= 0xFFFFFFFF
> typedef unsigned uint32;
> #define PRI32u "u"
> #define PRI32X "X"
> #else
> typedef unsigned long uint32;
> #define PRI32u "lu"
> #define PRI32X "lX"
> #endif
>
> and then do:
>
> uint32 blah = 42;
> printf("blah = %" PRI32u "\n", blah);
>
> You get the idea.

IIRC, James is currently using a modern C compiler. However, if
he later decides to downgrade to a primitive C compiler, that
won't work. ANSI C introduced automatic concatenation of adjacent
strings. That's just an FYI in case he plans to do so.


Rod Pemberton




ise...@gmail.com

unread,
May 18, 2013, 9:26:08 PM5/18/13
to
Something like this?: BareMetal OS - www.returninfinity.com/baremetal.html

A 16KiB kernel (and a 7KiB boot loader). Compatible with the Newlib C library so you can use printf(), etc.

-Ian (author of said kernel)

Alexei A. Frounze

unread,
May 19, 2013, 12:52:03 PM5/19/13
to
Whatever works works.

I've written pieces of the standard C library to use either the BIOS or the hardware directly. Not a big deal conceptually. You should've seen some of it in the package containing my FAT12/16/32 code.

Generally, the compiler itself should not generate OS-specific code, at least when it comes to C, which is a language that may be and often is used in freestanding environments.

From C99, chapter 4, Conformance:

The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program that does not use complex types and in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and <stdint.h>. A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.

See, there's no <stdio.h>, <time.h>, <stdlib.h> or even <string.h>!

Now, some compilers do generate OS-specific code. I don't remember if Borland C++ ever supported 16-bit DPMI programs, but Borland Pascal did. One OS-specific thing that was in the generated code is pointer arithmetic. In protected mode, as you know, addresses are based on the contents of the segment descriptor table and since those are DPMI/OS-specific the generated code is in some way DPMI/OS-specific as well. AFAIR, to get to the next 64K segment from the current one you needed to add 8 to the segment register (merely selecting the next descriptor in the table). In real/v86 mode the increment was 4096. If I'm not mistaken, though, the increment was read from a global variable. Yep, just checked, it was the SelectorInc variable in Borland Pascal.

Really, you don't need a lot of <stdio.h> and <stdlib.h> stuff to get going.

I wrote my SmallerC compiler (https://github.com/alexfru/SmallerC) in such a way that it can run on a very simple system using only the following 5 system calls:
- open(), read(), write(), close()
- exit()
and that lets me run it on a MIPS emulator like SPIM that provides these and a few more system calls (those other being for console I/O and memory management), but I only really need these 5. There isn't dynamic memory allocation other than for local on-stack variables.

If you stay low, you may get away with just this stuff.

Alex
0 new messages