[net.arch] What I miss in micro-processors

grzm@kuling.UUCP (Gunnar Blomberg/ADB) (08/31/85)

        I've been working in assembly language on micro-processors quite
a lot recently and there are a couple of features I've been missing
rather badly (please forgive me if these have been mentioned before,
I've very recently begun reading news).  I would be very glad for views
from other users on what kind of thing they would like to see included
as well as some response from the people who design these things (Is it
really true that the chips are designed solely by people who know
hardware and not software?  (the stuff from Intel would certainly
suggest that that is true...) :-))

1. Stack overflow detection.
 
  This is the one that really bugs me.  I don't know of any
micro-processor that does this.  Why is that?  In my mind this is
something that is badly needed, and coding the check inline would be too
much of a performance penalty.  This is also fundamentally different
from things like array bounds checking which, in principle, need only
be done while debugging the program and should never appear in a
"correct" program.  This is not true of stack overflow which can happen
in a perfectly good program.
  I am aware that many systems let their mmu handle the problem, but
that doesn't seem like a very good solution to me (it doesn't check for
stack overflow, only memory references "just above" the stack limit,
right?) and it doesn't help at all if the system doesn't have an mmu
(yes, all systems *should* have one, but...).

2. A quick subroutine call.

  What I would reaaly like to see here is something like the PDP-10 JSP
instruction, something that jumps to a subroutine and puts the return
address in a register instead of on the stack.  It should cut the
penalty of a subroutine call in about half.  This would really help out
many kinds of compilers in that the trade-off between putting stuff
in-line and calling a short subroutine would be changed in favour of the
subroutine.

        These are things I would very much like to see.  There are
others that I wouldn't mind at all, but they aren't very important
compared to the two above.

        I would guess that this would be a case for inviting discussion
from the net rather than telling people to mail to me, but as I said
above, I'm very new at this, so please use your judgment (and tell me if
I was wrong, I'm willing to learn).
-- 
Gunnar Blomberg (Grzm), Computing Science Dept., Uppsala University, Sweden
Tel: +46 18 13 76 02
UUCP: grzm@kuling.UUCP (...!{seismo,mcvax}!enea!kuling!hans)

schwrtze@csd2.UUCP (Eric Schwartz group) (09/04/85)

 Re: range checks. 

	"...leaving range checks out is rather like practising sailing on
shore with life belts and then leaving them on shore come the moment.."

	Knuth???

was it not the mariner probe that was lost due to a FORTRAN subscript error?

I agree with you to a point. For low-risk code leave them out, But for my 
money I would prefer to see the code in for systems like nuclear plants,
MX missiles etc..
--------------------
Hedley Rainnie. 

hedley@alaya   cmcl2!alaya!hedley

brownc@utah-cs.UUCP (Eric C. Brown) (09/04/85)

In article <796@kuling.UUCP> grzm@kuling.UUCP (Gunnar Blomberg/ADB) writes:
>
>        I've been working in assembly language on micro-processors quite
>a lot recently and there are a couple of features I've been missing
>rather badly....
>1. Stack overflow detection.
> 
>  This is the one that really bugs me.  I don't know of any
>micro-processor that does this.  Why is that?  In my mind this is

At the risk of being flamed by all the 68K lovers, I must point out that the
Intel 286 has stack overflow detection "for free" as part of their segment 
management (and may also have dedicated stack overflow/underflow detection);
it can be used by setting the stack limit <64K, and when the stack overflows
to 64K, you get an segment limit exception.

Eric C. Brown
brownc@utah-cs
..!{ihnp4, decvax}!utah-cs!brownc

res@ihlpl.UUCP (Rich Strebendt @ AT&T Information Systems - Indian Hill West; formerly) (09/05/85)

> 
>         I've been working in assembly language on micro-processors quite
> a lot recently and there are a couple of features I've been missing
> rather badly  ...  I would be very glad for views
> from other users on what kind of thing they would like to see included
> as well as some response from the people who design these things 
> 
> 1. Stack overflow detection.
>  
>   This is the one that really bugs me.  I don't know of any
> micro-processor that does this.  Why is that?  In my mind this is
> something that is badly needed, and coding the check inline would be too
> much of a performance penalty.  This is also fundamentally different
> from things like array bounds checking which, in principle, need only
> be done while debugging the program and should never appear in a
> "correct" program.  This is not true of stack overflow which can happen
> in a perfectly good program.
>   I am aware that many systems let their mmu handle the problem, but
> that doesn't seem like a very good solution to me (it doesn't check for
> stack overflow, only memory references "just above" the stack limit,
> right?) and it doesn't help at all if the system doesn't have an mmu
> (yes, all systems *should* have one, but...).

This feature is built into AT&T's WE(TM)-32100 Microprocessor.  I know,
because I just got a stack overflow exception on the other terminal
connected to a board I am developing firmware for!!  

					Rich Strebendt
					...!ihnp4!iwsl6!res

jans@orca.UUCP (Jan Steinman) (09/06/85)

In article <796@kuling.UUCP> grzm@kuling.UUCP (Gunnar Blomberg/ADB) writes:
>... there are a couple of features I've been missing rather badly...
>
>1. Stack overflow detection.
> 
>I am aware that many systems let their mmu handle the problem, but that
>doesn't seem like a very good solution to me (it doesn't check for stack
>overflow, only memory references "just above" the stack limit, right?)

The MMU is the answer.  If you want arbitrary bounds checking, that means
two registers and two internal compares on each stack access.  If you can
live with "page boundary" type checking, an internal mask and compare would
eliminate the need for the the registers, but would still consume time during
each stack access, unless it could be worked into the pipeline. (at
considerable design effort!)

The point is that this sort of thing is not free, or else everyone would do
it.  In my mind, it falls under the the "90/10" rule: it would increase stack
complexity by at least 90% while being used less than 10% of the time.

An internal (breif concession to Intel) MMU is the ideal place for such a
check.  An external MMU is the only other place it belongs.
>
>2. A quick subroutine call.
>
>  What I would reaaly like to see here is something like the PDP-10 JSP
>instruction, something that jumps to a subroutine and puts the return
>address in a register instead of on the stack.

I hope you never try anything recursive this way!  Current popular recursive-
capable languages don't have any way to guarantee a given routine will never
be used recursively, so compilers for such languages (Pascal, C, Ada, etc.)
would never use such an instruction.  As for non-recursive assembly code, I
would look carefully at re-designing your entire calling scheme.  If time-
optimal, macrofy and in-line the calls (with the added advantage of being able
to use arbitrary registers).  If stack space-optimal, write a macro that
sticks the PC in a register, then jumps.

Guess what I'm really trying to say is that I don't see enough use for either
of these things to justify the effort needed to put them in.

My favorite peeve is a rather restricted one, as yours are.  I write
interpreters and would love a multi-way, in-line, absolute indexed branch.
Both VAX and National came so close, but their CASE instructions are PC
relative, and must be a constant distance from the routines (VAX) or jump
table (National).  This means in-line coding of the routine dispatcher is not
possible with this instruction.  It would be so nice to end each routine with
a CASE (R7),TABLE and have control passed to the routine who's address is at
TABLE+R7*size.
-- 
:::::: Jan Steinman		Box 1000, MS 61-161	(w)503/685-2843 ::::::
:::::: tektronix!tekecs!jans	Wilsonville, OR 97070	(h)503/657-7703 ::::::

kds@intelca.UUCP (Ken Shoemaker) (09/07/85)

> >
> >2. A quick subroutine call.
> >
> >  What I would reaaly like to see here is something like the PDP-10 JSP
> >instruction, something that jumps to a subroutine and puts the return
> >address in a register instead of on the stack.

I'm suprised no one has brought up the 1802 on this one.  What this little
8-bit bugger has is a set of 16 16-bit registers, any of which can be
used as the program counter or the stack pointer.  There are two 4-bit
registers that determine which to use that can be changed by the user.
The advertised technique for fast subroutines is to dedicate one of the
registers to a certain procedure and then switch the pc to that register
whenever you want to call the procedure.  Of course, this works real
well, especially if the last instruction of the procedure is a jump
to the pseudo-return which is placed just before the first instruction
of the procedure.  It was very important to keep your 16-bit registers
right, since the only way to get to them was as two halves through
a single 8-bit accumulator register.  Anyway, I hope I have the details
of this right from the far reaches of my memory!
-- 
...and I'm sure it wouldn't interest anybody outside of a small circle
of friends...

Ken Shoemaker, Microprocessor Design for a large, Silicon Valley firm

{pur-ee,hplabs,amd,scgvaxd,dual,qantel}!intelca!kds
	
---the above views are personal.  They may not represent those of the
	employer of its submitter.

chris@umcp-cs.UUCP (Chris Torek) (09/08/85)

> ...  It would be so nice to end each routine with a CASE (R7),TABLE
> and have control passed to the routine who's address is at TABLE+R7*size.

How about

	movl	table[r7],pc

or something like that?
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

mayer@rochester.UUCP (Jim Mayer) (09/08/85)

In article <1713@orca.UUCP> jans@orca.UUCP (Jan Steinman) writes:
>In article <796@kuling.UUCP> grzm@kuling.UUCP (Gunnar Blomberg/ADB) writes:
>>... there are a couple of features I've been missing rather badly...
>>...
>>2. A quick subroutine call.
>>
>>  What I would really like to see here is something like the PDP-10 JSP
>>instruction, something that jumps to a subroutine and puts the return
>>address in a register instead of on the stack.
>
>I hope you never try anything recursive this way!  Current popular recursive-
>capable languages don't have any way to guarantee a given routine will never
>be used recursively, so compilers for such languages (Pascal, C, Ada, etc.)
>would never use such an instruction.  As for non-recursive assembly code, I
>would look carefully at re-designing your entire calling scheme.  If time-
>optimal, macrofy and in-line the calls (with the added advantage of being able
>to use arbitrary registers).  If stack space-optimal, write a macro that
>sticks the PC in a register, then jumps.
>
>Guess what I'm really trying to say is that I don't see enough use for either
>of these things to justify the effort needed to put them in.
>....
I would also like to see a simple, register based, calling sequence on
microprocessors.  Here are my reasons:

1. Simple compilers for most languages usually start off procedures
   by saving a bunch of registers, and finish by restoring the same
   set.  The trend for CISC machines (vax, 68000, etc) is to provide
   some variant on the "push multiple registers"/"save according to
   register mask" theme.  Given this kind of prelude, it doesn't really
   matter whether the PC is pushed on the stack at the JSR, or at the
   MOVEM.  Recursion still works fine.  And since simple compilers
   usually don't do to well at allocating registers across procedure
   calls, the cost of the tied up register is not to great either.
   This assumes, of course, a register intensive architecture.

2. It is quite easy to detect a large class of routines in ANY LANGUAGE
   that are not called recursively.  In the most general case, just
   build a call graph and look for cycles.  Given a more traditional
   compile&link compiler architecture it would still pay to look for
   routines that don't call any other functions (or any functions
   outside of the current module/source file).

3. Finally, to throw a new twist into the time optimal/space optimal
   tradeoff, consider the effect of compiler generated specialized
   calling sequences.  Given some run time statistics a compiler can
   identify calls that would benefit from inline or specialized calling
   sequences.  The same techniques can be used to propagate information
   about register usage.  In fact, one can view inline expansion as
   nothing more than one extreme of calling sequence optimization.  The
   optimizations are driven by execution time profiling information and
   estimates of the potential for further traditional optimizations
   constrained by a space bound.  For more information see Gene Ball's
   Ph.D.  dissertation:

	John Eugene Ball
	Program Improvement by the Selective Integration of Procedure Calls
	Ph.D. Thesis
	University of Rochester, 1982.

   Also, for a simpler approach that only handles inline expansion and
   does not consider the effects of further optimizations see:

	Robert W. Scheifler
	An Analysis of Inline Substitution for a Structured Programming Language
	CACM, Volume 20, Number 9
	September 1977, pages 647-654.

4. I guess that where I differ from the original poster is that I don't
   want a stack based calling sequence at all!  Stack based calling
   sequences on machines with lots of registers seem to me like a
   perfect example of a premature optimization.  My general feeling is
   that this kind of "low level" high level language support (eg. stack
   based calls, index instructions, bounds checking) is usually not
   worth adding since an optimizing compiler can do a better job of
   speeding things up anyway.  On the other hand, specialized high
   level microcode/hardware support for things like checksums, context
   switching, message passing, and FFT's can be big wins.  I'm
   especially fond of writable control stores.

Boy is this long.

-- Jim Mayer					University of Rochester
(arpa) mayer@Rochester.ARPA			Department of Computer Science
(uucp) rochester!mayer				Ray P. Hylan Building
       (via allegra, decvax, or seismo)		Rochester, New York 14627

chuck@dartvax.UUCP (Chuck Simmons) (09/09/85)

> In article <796@kuling.UUCP> grzm@kuling.UUCP (Gunnar Blomberg/ADB) writes:
> >2. A quick subroutine call.
> >
> >  What I would reaaly like to see here is something like the PDP-10 JSP
> >instruction, something that jumps to a subroutine and puts the return
> >address in a register instead of on the stack.
> 
> I hope you never try anything recursive this way!  Current popular recursive-
> capable languages don't have any way to guarantee a given routine will never
> be used recursively, so compilers for such languages (Pascal, C, Ada, etc.)
> would never use such an instruction.  

*tee hee*  Actually, our Honeywell has such an instruction.  Our PL/I,
Pascal, and Basic compilers (all of which support recursion) all make heavy
use of this instruction as it is the only reasonable way of calling a 
subroutine.

It's true that all of the compiled subroutines immediately store the
return address in the stack.  However, in our runtime library, we only
store the return address when we must.  This tends to make the runtime
library routines blazingly fast, if slightly difficult to maintain.
This should be contrasted to the approach used on our Unix Vax where every
subroutine call tends to push a few registers on the stack, even if it
is known that the subroutine is non-recursive, and there are registers
to spare.  By the way, our Honeywell typically runs with 200 users who seldom
notice a delay.  Our Unix Vax can barely handle 20.

(Don't get me wrong.  Personally, I love the Vax architechture.
If our Vax could make love, I'd marry her.)

chuck@dartvax

guy@sun.uucp (Guy Harris) (09/10/85)

>  Re: range checks. 
> ... 
> I agree with you to a point. For low-risk code leave them out, But for my 
> money I would prefer to see the code in for systems like nuclear plants,
> MX missiles etc..

I'm not sure I'd feel very comfortable knowing that if the code controlling
a nuclear power plant or an MX got a subscript error, it would dutifully
print a traceback on the console terminal...

I'd rather have that code verified not to ever generate subscript errors
(except as the result of hardware errors, but if your hardware is that
flakey, subscript errors are probably the least of your worries).

	Guy Harris

mouse@mcgill-vision.UUCP (der Mouse) (09/11/85)

> > ...  It would be so nice to end each routine with a CASE (R7),TABLE
> > and have control passed to the routine who's address is at TABLE+R7*size.
>
> How about
>
>	movl	table[r7],pc
>
> or something like that?

     That's what I thought too.  I considered trying something like

	jmp	*_table[r7]

but unfortunately the way indexed mode works, that  comes out grouped as
(*_table)[r7]  instead of  *(_table[r7]).    So  I  wrote the  following
routine:

	.globl	_callroutine
	.globl	_table
_callroutine:
	.word	0xffc
	movl		4(ap),r0
	addl3		$2,_table[r0],pc

This assembled silently.   I  wrote a C test  driver for it,  ran it and
boom, illegal instruction.  Adb told me pc was just after the addl3 (the
instruction  there  was a "halt").  Put in "calls $0, _abort" there so I
could tell, and sure enough, this time it called abort before dying.  So
the  addl3 wasn't functioning as a  jump.   I  look  at the architecture
handbook:

3.4 GENERAL MODE ADDRESSING FORMATS

3.4.1 Register Mode

     [...]. PC may  not be used  in register mode  addressing.  If PC is
read,  the  value read  is UNPREDICTABLE.   If PC  is  written, the next
instruction  executed  or the next operand specified  is  UNPREDICTABLE.
[...]

     So I guess we can't do that.  We seem to be reduced to

	movl			_table[r7],r0
	jmp (calls, etc)	(r0)

which I haven't tried, but I feel certain would work.

     Ugh.
-- 
					der Mouse

{ihnp4,decvax,akgua,etc}!utcsri!mcgill-vision!mouse
philabs!micomvax!musocs!mcgill-vision!mouse

Hacker: One responsible for destroying /
Wizard: One responsible for recovering it afterward

peterb@pbear.UUCP (09/12/85)

/* Written 11:48 am  Sep  5, 1985 by myriasa!cg in pbear:net.arch */

>First, keep in mind that I'm a compiler writer by trade, so I like the
>idea of a pure stack architecture because it's so easy to generate code
>for (I did it for a machine I designed and emulated).

Yes that's true, but the speed of that "simple-to-generate" code is quite
expensive. No matter how you cut it, you still have to optimize the code
no matter how fast the hardware is since someone is going to want a faster
and cheaper version of the same thing.

>I've been told by a couple of people who are normally well informed that
>a pure stack architecture just isn't practical. They have NOT been able
>to convince me of this. Anybody out there want to try?

A PURE stack environment has no static variable space, so it is quite
expensive to access variables ACROSS stack frames by following static links,
or by using a display to access a constant address variable. Also on
procedure calls, the hardware has to spend a bit of bus bandwidth and time
building up the display to keep the static scope of the program intact.
There are ways around it by having two types of procedures: those that call
others, and those that are "leafs"(don't call any others). For the ones that
don't call, there is no need to set up a new stack frame since the last on
is still usable.

Also PURE stack environments have no registers, so much of the time is
spent accessing the top of stack.

Also in a pure stack environment, IO has a real problem since there are no
addresses, or if there are, there is no way to fix them are compile time.

>You say that a stack machine spends far too much time accessing the stack
>in memory. Easy - have the top, say, 100 values of the stack in on-board
>registers.

No, you don't need that many, 8 would do just fine. Look at the HP RPN
calculators. They only have a 4 deep stack, and can do quite a bit with it.

>You say the large register set requires too much flushing on a task
>switch (or redundant stores if you do it in the background). Simple -
>don't flush it so much; have about 4 of them, with control over the
>flushing policies that are to be used. One can be reserved for the
>supervisor, and is only flushed if there is no bus activity at all. Also,
>when the on-board top-of-stack is close to being full (90%?), the far top
>end of it can be written out (NOT flushed) during any idle bus cycles.
>The remaining top-of-stacks are used for user tasks (it may be better
>to have more of them, but smaller - depends on how often you task switch
>and on how many tasks you plan on having). They still need not be write-
>through, but would want the same "write on nearly full" policy. The stack
>sets for non-active user tasks can be written out whenever convenient,
>probably in LRU order (the goal would be to have an clean one (all modified
>values written out) when one is needed for another task).

See above, Also you can keep one in reserve and suspend execution until
stack space is available. It would actually be simpler to put a cached MMU
in between the memory and the processor. Then when you fault, you can switch
tasks with only two register changes (stack pointer and program pointer) and
two page swaps (one for code, other for TOS). Then fault in the other
information.

>All those registers won't fit on available chip real-estate. Well, given
>that all of your normal registers and most of your addressing modes go
>away, there should be lots of space. (This very similar to the RISC
>argument that gives you lots of room for registers when you simplify
>the instruction set.)

More registers are expensive in operation costs. As above it gets real
complex to force the flush of this huge register set or time to writes
at idle bus times (which would then take up the real esate that the
registers sit on). So if you use huge register sets, you pay in complexity
and cost of operation.

The RISC arguement is that in simplifying the instruction, the speed of the
system can be increased.

>You can't take the address of one of the stack elements (at least not
>without a lot of support hardware). Fine. I'm quite willing to have the
>compiler allocate some variables in non-stack storage. I'm even willing
>to have to explicitly tell the compiler which ones (sort of the inverse of
>the way 'register' is treated in C). This may mean having two stacks - one
>for "small" variables and one for those whose address is needed. Again,
>I say fine. The same holds for variables shared between tasks ('volatile'
>in the new C).

arrghhh, again, have the stack be pointing into a datazone with fixed
addresses. this way the static data can be at one end(like floating and
string constants), and the stack grow in from the other. Also the address
of a variable is then simply a true address, with no pain.

Peter Barada
{ihnp4!inmet|{harvard|cca}!ima}!pbear!peterb

bjorn@alberta.UUCP (Bjorn R. Bjornsson) (09/12/85)

In article <1713@orca.UUCP> jans@orca.UUCP (Jan Steinman) writes
>.....................  If stack space-optimal, write a macro that
>sticks the PC in a register, then jumps.
>
>Guess what I'm really trying to say is that I don't see enough use for either
>of these things to justify the effort needed to put them in.

Gunnar's point (and rightly so) was that this takes more space and time
than a dedicated instruction.  A dedicated instruction may dramatically
shift the space/time tradeoff of inline expansion (greater space,
greater speed) versus local call (less space, less speed) in favor
of the latter.

>My favorite peeve is a rather restricted one, as yours are.  I write
>interpreters and would love a multi-way, in-line, absolute indexed branch.
>Both VAX and National came so close, but their CASE instructions are PC
>relative, and must be a constant distance from the routines (VAX) or jump
>table (National).  This means in-line coding of the routine dispatcher is not
>possible with this instruction.  It would be so nice to end each routine with
>a CASE (R7),TABLE and have control passed to the routine who's address is at
>TABLE+R7*size.

So your favourite peeve is more valid than Gunnar's, why don't you take
your own advice and:

	ashl	$2,r7,r7
	jmp	TABLE(r7)

You could even arrange things, such that the multiplication
of r7 by four is eliminated, and get away with:

	jmp	TABLE(r7)

In the VAX the location of the table is fixed with respect to the
case instruction, but the table contains displacements (ie relative
to pc/and table), whereas the the ns32000 case instruction is really
just a vanilla branch instruction that allows the full complement of
ns32000 addressing modes.

In article <1517@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes:
>> ...  It would be so nice to end each routine with a CASE (R7),TABLE
>> and have control passed to the routine who's address is at TABLE+R7*size.
>
>How about
>
>	movl	table[r7],pc
>
>or something like that?

"something like that", ie. register mode use of the pc, produces
unpredictable results on VAX processors.

		Bjorn R. Bjornsson
		ihnp4!alberta!bjorn

peter@graffiti.UUCP (Peter da Silva) (09/13/85)

> 	"...leaving range checks out is rather like practising sailing on
> shore with life belts and then leaving them on shore come the moment.."
> 
> 	Knuth???
> 
> was it not the mariner probe that was lost due to a FORTRAN subscript error?
> 
> I agree with you to a point. For low-risk code leave them out, But for my 
> money I would prefer to see the code in for systems like nuclear plants,
> MX missiles etc..

What should the code do when a range-check occurs? Print out an error message
on ticker-tape & hang? Do nothing? A better analogy, perhaps, would be...

	"...like practicing sailing on shore with a mechanic [safety harness]
and leaving it on shore come the moment..."

...you no longer have anything to attach them to.

phil@unisoft.UUCP (phil ronzone) (09/25/85)

In article <191@graffiti.UUCP> peter@graffiti.UUCP (Peter da Silva) writes:
>> 	"...leaving range checks out is rather like practising sailing on
>> shore with life belts and then leaving them on shore come the moment.."
>> 
>> 	Knuth???
>> 
>> was it not the mariner probe that was lost due to a FORTRAN subscript error?
>> 
>> I agree with you to a point. For low-risk code leave them out, But for my 
>> money I would prefer to see the code in for systems like nuclear plants,
>> MX missiles etc..
>
>What should the code do when a range-check occurs? Print out an error message
>on ticker-tape & hang? Do nothing? A better analogy, perhaps, would be...
>
>	"...like practicing sailing on shore with a mechanic [safety harness]
>and leaving it on shore come the moment..."
>
>...you no longer have anything to attach them to.

This is the kind of ``religous'' issue that probably ends up in net.flame,
but as a decade-long C programmer, I find about every 3 years some
``discussion'' with a proponent of a more-or-less highly typed language
(Ada most recent) over the ``virtues'' of Ada and its error checking over
(denigration inserted here) C.

Shucks - but I still CAN'T see how much the poor pilot in an F16 with an
Ada programmed fire-control computer is going to be as a Mig-27 bears down
on him, and right when he hears the lock-on buzz to fire his own missile --

     Ada runtime error 498: subscript i value 23 out of range for array x (20)

I mean,
   
     Bus error - core dumped

reads quicker and thus gives the pilot a faster ``oh shit'' response time
to take evasive action .... :-) :-)

However - along these lines, there is a UNIX loader for a AT&T 3bx machine
that allows org'ing at 4K, to leave the first page no-read/no-write to
catch the hordes of AT&T invalid references to location 0.

cdshaw@watmum.UUCP (Chris Shaw) (09/27/85)

In article <191@graffiti.UUCP> peter@graffiti.UUCP (Peter da Silva) writes:
>> 
>> was it not the mariner probe that was lost due to a FORTRAN subscript error?
>> 
>> I agree with you to a point. For low-risk code leave them out, But for my 
>> money I would prefer to see the code in for systems like nuclear plants,
>> MX missiles etc..
>
>What should the code do when a range-check occurs? Print out an error message
>on ticker-tape & hang? Do nothing? A better analogy, perhaps, would be...
>
>	"...like practicing sailing on shore with a mechanic [safety harness]
>and leaving it on shore come the moment..."
>
>...you no longer have anything to attach them to.

This seems to be a popular attitude... "we can't be bothered to think today,
so we'll just assume that we can't think of ways to use range checking".

Kinda dumb, don't you think? 

Someone mentioned calling ADA's exception package,
which is probably a good thing. Another possibility (in the Mariner probe 
example) would be to "call home" if the exception package doesn't get the
probe "out of the jam".

If we're going to have an analogy fight, not having belts is like not telling
a child what his home address/phone number is in case he gets lost. If the
child gets lost, he's out of luck. If he has some information, (i.e. an 
exception handler) he may be able to find his way home none the worse for wear.

Looking at Computer Science as mere programming as opposed to
some branch of engineering is a "bad attitude", is unprofessional, etc.

The problem, of course, is that not enough people see software tasks as 
warranting the ideals of Professional Engineering.

Chris Shaw    watmath!watmum!cdshaw  or  cdshaw@watmath
University of Waterloo
In doubt?  Eat hot high-speed death -- the experts' choice in gastric vileness !

dms@mit-hermes.ARPA (David M. Siegel) (10/01/85)

   From: phil@unisoft.UUCP (phil ronzone)
   Date: 25 Sep 85 07:37:44 GMT

   Shucks - but I still CAN'T see how much the poor pilot in an F16 with an
   Ada programmed fire-control computer is going to be as a Mig-27 bears down
   on him, and right when he hears the lock-on buzz to fire his own missile --

	Ada runtime error 498: subscript i value 23 out of range for array x (20)

True, this would be of little use to the pilot. But if his little
black box recording the status of the various systems on the aircraft
were recovered, the run time checking could reveal useful information
for fixing the problem.

Another point worth mentioning, when an out-of-bounds array reference
is made you can't be sure that your os will respond "bus error".
Instead, your program might just give the wrong answer. These kinds of
problems can easily go undetected.

-Dave

-- 
					Arpa:	dms@mit-hermes.arpa
					Usenet:	mit-eddie!mit-hermes!dms

david@daisy.UUCP (David Schachter) (10/01/85)

On our 80286-based workstation, we set the descriptor table
entry for segment #0 to be an invalid entry.  We force the
system memory manager to set memory to zero before passing
the requested block to the requestor.  Thus, uninitialized
pointers get selectors of 0.  When a reference is made via
one of these nasty points, the CPU traps with an "invalid
selector" trap.  Takes care of most of the bad pointer
problems.  For the remainder, we tell the memory manager to
fill memory with 0FAF4H instead of 0.  This pattern is
never a valid selector.  If used as an index into a table,
it will usually cause a segment overrun error unless the
table is of byte-wide quantities.  If executed, it halts
the CPU with interrupts enabled.
  
Of course, the 80286 traps stack overflow/underflow and
any other attempts to run off the end of segments.  Thus,
uninitialized variables, which were a big problem on the
8086, have ceased to be major time-wasters on the 80286.

By the way, forcing the system memory manager to fill
segments with a value before returning them to the requestor
costs << one percent in run time.
  
In addition, to further improve the ability to detect
uninitialized variables, we have conventions on what
constitutes invalid values.  Usually, 0FFH and 0FFFFH
are invalid values for bytes and words, by Daisy convention.
Programmers are "encouraged" to set all data area to these
values during program initialization and to check variables
for these values as consistency checks during program
runtime.
  
These techniques aren't cure-alls but they solve the
majority of the problem for us.

mahar@weitek.UUCP (mahar) (10/03/85)

  I think there is no real harm in having range checking in a program. It
is important that somthing reasonable be done when an error occurs. This
is not always the case in commercial products. I was using a turn key
cad station when I did somthing wrong. I don't remember exactly what but
the system responded with:
	Range check error at line 143 in module intcore
and returned to the operating system. This was a turn key system so I had
no documentation on what the operating system was, its commands, or, more
importantly, how to recover and save the five hours work that was lost.
The only thing I could do was reboot the system and start over.
If the system were properly designed this condition whould have been at most
a little bothersom.
  Most programming dogma declares that a correct program that runs slow is
better then an incorrect one that is fast.
For the most part this makes sense. There are, however, cases where this is
not so true. Suppose there is an application which has a few well know bugs.
Would the user community prefer that version of the application over one
that has fixed the bugs but run 100000 times slower? 2 times? Most the users
I know would not switch if they could notice any performance loss.
  Another concern reguarding speed is real time applications. It is easy,
and common, to imagine a program which will work without range checking
and not work with. In many video applicatons, the program does not work if
the screen can't be updated in a single frame of 1/60th of a second. If you
miss by as much as a micro second your dead. Under those circumstances I
would gladly sacrifice range checking.
  In other postings the idea of forceing a parity error on uninitialized
ram locations was presented. This has, as far as I can tell, the property
that uninitialized accesses are undistinguishable from parity errors. This
can cause a problem. On this system, the majority of parity errors will
uninitialized variables. What if you get a real parity error? As a program
developer, my first guess whould be that this was an uninitialized variable.
What I would not be able to do is reproduce the bug. This is the stuff that
nightmares are made of. After a review of the code I whould not find anything
wrong but I whould never be certain that this 'hidden bug' whouldn't crop
up again.