[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Please help with BinSCII
Jeff Blakeney writes ...
>
> On Mon, 03 Jul 2000 00:22:45 -0500, Rubywand <rubywand@swbell.net>
> wrote:
>
> > It sounds like you are saying that, after running a program using an
> > ONERR GOTO without doing corresponding stack cleanup CALLs, you will
> > end up at the BASIC prompt with top-of-stack being positioned lower
> > than usual. How did you determine that this happens?
>
> On my IIgs, I launched BASIC.SYSTEM and typed in this simple test
> program:
>
> 10 ONERR GOTO 30
> 20 GOTO 20
> 30 END
>
> I then dropped into the monitor and typed CTRL-E and pressed return
> and noted the stack address. I returned to Applesoft and ran my
> program and pressed CTRL-C to cause an "error" and I was returned to
> the Applesoft prompt. I again dropped into the monitor and typed
> CTRL-E and noted that the stack address was not two bytes lower than
> it had been before.
>
> I just double checked it again and did a couple extra tests. If you
> just have the program:
>
> 20 GOTO 20
>
> and run it and end it with CTRL-C the stack stays at the same value.
> If you have the program:
>
> 10 ONERR GOTO 30
> 20 GOTO 20
> 30 CALL -3288: POKE 216,0
>
> and run it and end it with CTRL-C the stay stays at the same value.
>
> It is only if you use the first program, which uses an ONERR GOTO
> statement and doesn't clean up the stack that the stack pointer
> changes after the program is run.
Interesting and definitely worth knowing about! Thanks for taking the
time to outline your tests.
I was wondering if a program using an ONERR GOTO with no cleanup which
terminates with an END (instead of an error) would return to the BASIC prompt
with the stack pointer reset. The program used to check this idea is listed
below:
10 CALL 768
20 ONERR GOTO 80
30 GET X
40 A = 1/X
50 CALL 768
60 IF A <> 1 THEN 30
70 END
80 GOTO 50
The routine which is CALLed moves the stack pointer to X, sets Y to $00,
JSR's to a monitor routine to display Y and X regs, and RETURNs.
300: BA
301: A0 00
303: 20 40 F9
306: 60
The program was run on a II+ under DOS 3.3 and ProDOS.
As expected, so long as there is no bad entry for X there is no change
between the first display (Line 10) and subsequent displays at Line 50. And,
if you enter a "1", the program exits; whereupon a CALL 768 gives the same
value for the pointer. (BTW, this value may be off a bit from the actual
value at the time of the CALL 768.)
If you run the program and enter bad values for X (e.g. "0", letters,
etc.) the value for the stack pointer displayed at Line 50 marches downward
just as you say it should.
Under ProDOS, the program will crash a bit above a pointer value of $40.
Under DOS 3.3, the pointer eventually wraps back to the top and starts down
again. (The program never did crash.)
Exiting the program and doing a CALL 768 displays the same value as the
one last shown. So, an END does not set the stack pointer back near the top
(which seems to normally be $F6 under Applesoft using the particular CALL to
sample the pointer). Under DOS 3.3, a RESET will move the pointer up a bit
higher (CALL 768 shows $FA).
Something that's kind of interesting is that there are some commands
which automatically reset the stack pointer near the top. LOAD and NEW both
do this.
As you say, plugging in the CALL -3288 at Line 80 eliminates stack
pointer changes.
10 CALL 768
20 ONERR GOTO 80
30 GET X
40 A = 1/X
50 CALL 768
60 IF A <> 1 THEN 30
70 END
80 CALL -3288: GOTO 50
You can press bad keys as long as you like and the pointer is solid at $F6.
Obviously, just on general principles, having a stable stack pointer is
a good thing. (Like, you do not need to wonder what might happen if you
don't.) So, the CALL -3288 is worthwhile in a program like those discussed--
i.e. one where the error occurs in main line code.
CALL -3288 turns out to be unstable when an error occurs inside a
subroutine. That is, for some errors the stack is restored and for some it is
not and the program crashes.
A fairly good workaround seems to be to direct ONERR GOTOs to the main
line and use a CALL which reinits the stack instead of trying to fix it.
William Luebbert's book "What's Where in the Apple II" identifies a STKINI
CALL at $D863 (-10621) which does this.
This program maintains the stack:
10 CALL 768
20 ONERR GOTO 80
30 GET X
40 A = 1/X
50 CALL 768
60 IF A <> 1 THEN 30
70 END
80 CALL -10621: GOTO 50
This program, where the error occurs in a subroutine, also maintains the
stack:
10 CALL 768
20 ONERR GOTO 80
30 GET X
40 GOSUB 90
50 CALL 768
60 IF A <> 1 THEN 30
70 END
80 CALL -10621: GOTO 50
90 A = 1/X: RETURN
Rubywand