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.