[comp.sys.acorn] Saving the old pc in APCS

csuwr@warwick.ac.uk (Derek Hunter) (04/04/91)

In article <6080@acorn.co.uk> john@acorn.co.uk (John Bowler) writes:
>
>                                                    Ok, we admit
>it, you have to use that instruction sequence :-)

Just as well I decided to follow APCS then. (Can I quote you on the
 mandatory nature of the code fraction? ;-)

Incidentally, a fair while ago, you mentioned that debugging compilers is
 easier if one follows APCS. While at the moment, I can inspect the code
 `by hand' [snigger] and since it's totally unoptimised, it's very readable,
 I imagine pointers will start going awry later when the computer decides
 to get clever with the code. !! Scrounge alert !! Can I get my hands on some
 of Acorn's compiler development programs, or (and perhaps, more
 importantly), some blurfl about the interface for the (latest! :-)
 Shared C Lib, like, man, for little or no bread?

>                                       . . .  the callee can check to
>see if there is enough room on the stack.  If there isn't . . .

Urk! At the moment, my code's code does nothing to check about the stack
 size, or anything. Can I just rely on the system stack for the moment
 (especially if it's running as a module), or will I have to set something
 up at the start of the code? (I doubt it will be running as RISCware
 just yet...)

How about having my stack floating off somewhere towards the top of
 application space (Just under the 4 megabyte boundary) and mapping pages
 into (out of) place as I need them (although I suppose that a 8/16/32K page
 multiple is a bit much for a single program's stack), or must I limit myself
 to tucking the stack into heap space, in which case, how does one determine
 an appropriate amount to grab for heap space at the start?

I was rather hoping to avoid set-up, run-time and exit code, but it looks
 like things are rather more complicated than I had hoped (naive old me).

  .-------------------------------------------------------------------.
  | `It looks like a recursive descent parser that's been trodden on' |
  `---------------------+------------------------+--------------------'
                        | csuwr@cu.warwick.ac.uk |
                        `------------------------'

john@acorn.co.uk (John Bowler) (04/11/91)

In article <V'X&9{^@warwick.ac.uk> csuwr@warwick.ac.uk (Derek Hunter) writes:
>Incidentally, a fair while ago, you mentioned that debugging compilers is
> easier if one follows APCS. While at the moment, I can inspect the code
> `by hand' [snigger] and since it's totally unoptimised, it's very readable,
> I imagine pointers will start going awry later when the computer decides
> to get clever with the code. !! Scrounge alert !! Can I get my hands on some
> of Acorn's compiler development programs,

Ho ho.  What compiler development programs ? :-)  The APCS provides
sufficient information to allow a trace back to be produced by something
which can read the symbol information produced by a linker - for example
ASD under RISC OS or adb under RISC iX.  Its approaching 10 years since I've
used anything more sophisticated when debugging programs than the simple
trace back, examination of the program memory and compiled code, and
appropriately placed printf statements.  The latter technique is normally
of little use when debugging compiler operation (addition of the printf's
normally changes the compiler generated code too much).

>                                           or (and perhaps, more
> importantly), some blurfl about the interface for the (latest! :-)
> Shared C Lib,

The shared C library interface is the normal procedure interface.
If you have a linkable shared C library, you have the stub procedures
which actually allow entry to the real library.

>               like, man, for little or no bread?

Ah, well, you have to buy the linkable version of the library; so you need
ANSI C Release 3 (to get the latest version), then you follow the
instructions around page 395 of the manual, which tell you how to interface
a language to the kernel.  As far as I am aware there is no other way
of doing it - does anyone know differently?

>... At the moment, my code's code does nothing to check about the stack
> size, or anything. Can I just rely on the system stack for the moment
> (especially if it's running as a module),
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I don't know about this - anyone else like to comment?  The manual does
say ``modules written in C should *not* be compiled with stack limit
checking disabled''.

>                                           or will I have to set something
> up at the start of the code? (I doubt it will be running as RISCware
> just yet...)

Even if you use our C library you can implement your own stack overflow
handling.  The problem with C library usage is that it forces some
constraints on the behaviour of the program which uses it - with RISC OS
that program must provide some environment (this also applies in RISC iX -
the library code requires a couple of pieces of initialisation, but the
overhead is far less than in RISC OS).  If you don't allow use of the
standard C library you can avoid setting up that environment.  You can still
use APCS (obviously), but you can implement stack overflow checking
completely different.  For example, in RISC iX there is no stack overflow
check code - instead the RISC iX kernel handles stack extension
automatically.

>How about having my stack floating off somewhere towards the top of
> application space (Just under the 4 megabyte boundary) and mapping pages
> into (out of) place as I need them

This is bascially what RISC iX does; it is compatible with the APCS, but is
not compatible with the current RISC OS wimp environment.  This gives each
application a memory space which is described solely by its length (it is
always based at 8000H).  You need the wimp to allow two memory slots, one
starting at 8000H, the other at the top of the possible application data
space.  It won't do that...

>                                    (although I suppose that a 8/16/32K page
> multiple is a bit much for a single program's stack),

Not necessarily.  Many programs use quite large locally allocated buffers,
for example ``char filename[256]'' (char filename[1024] on UNIX systems!)
32k is, maybe, a little excessive for small applications, but it is very
difficult to say.

>                                                       or must I limit myself
> to tucking the stack into heap space, in which case, how does one determine
> an appropriate amount to grab for heap space at the start?

The same problem again.  Theoretically a compiler could meter stack usage
during compilation, and produce output which could be used to produce a
complete call graph plus an formula to determine maximum stack size (extra
information is needed for recursive procedures).  This could be used at the
link step to control how the program initialised the stack.  If you can't
do this you just guess; we've tried this (guessing) many times.  Last time
I was involved in such discussions people were suggesting 2-8k bytes, with
a smaller size for stack extensions, but that was a different operating
system and a different language.

>I was rather hoping to avoid set-up, run-time and exit code, but it looks
> like things are rather more complicated than I had hoped (naive old me).

It is well worth avoiding these things wherever possible.  In particular
set-up code for a given language system can make inter-language calling into
a nightmare.  RISC iX is almost minimal; it generates the argc, argv and
environ arguments for main(), stores the environ value and, for shared
library support, stores the end of the program data and text segments in
the shared library static data (this effectively initialises the malloc()
interface).  RISC OS is more complex.  It initialises the stack, memory IO
sub-systems, and possibly others, and provides appropriate support for stack
extension, stack unwinding and other things.

John Bowler (jbowler@acorn.co.uk)