dmb@TIS.COM (David M. Baggett) (01/06/90)
The original thread was about changing resolution from within a process termination handler (i.e., a function installed at the GEM process termination vector 0x102). Atari's Allan Pratt claimed that you can call Setscreen from within such a handler. He was indeed correct. (I was a bit skeptical after the 36th crash, but now I Believe.) HOWEVER, my frustrating attempts to get this to work indicate that the OS hooks are different in his compiler than in Sozobon C. Calling Setscreen with Sozobon's standard xbios() call will cause an exception. I.e., adding *just* Setscreen(-1L, -1L, 1); to my process termination handler causes the handler to RTS to an illegal instruction. Note that this call is #defined in <osbind.h> and turns into xbios(5, -1L, -1L, 1) (i.e., it calls the xbios hook in dstart.o, provided with Sozobon). For the hell of it, I tried writing my own xbios hook, assuming Sozobon's stack checking was causing the problem. It wasn't the stack checking. (At least, that wasn't the only thing.) Saving the stack pointer before the trap and restoring it afterwards fixes things. I don't know why the bios trashes the stack when called from a termination handler. Perhaps a wizardly Atari person could comment. Also, I'm wondering if dstart.o is in error for not saving the stack pointer, or if Atari is in error for writing bios code that trashes the stack pointer, or if somebody else is in error (maybe me). (Well, _somebody_ has to be in error! Who can we flame if no one's in error?) In any case, anyone who's having trouble getting bios calls to work from a termination handler (and I believe this is a problem in Laser C as well) should try using the OS hooks below. They work with Sozobon, and as far as I know should work with other C's too. Dave Baggett dmb@TIS.COM ----------------------------------- >8 --------------------------------------- ; ; Operating system hooks for C with stack pointer saves. ; These are useful for calling bios routines from within a process termination ; function; i.e., a function installed at GEM process termination vector 0x102 ; ; (Modified from Dlibs code in dstart.o) ; .globl __gemdos __bios __xbios ; ; long _gemdos(function, [parameter, ...]) ; int function; ; __gemdos: move.l (A7)+, traprtn ; save return address move.l A7, saveA7 ; save stack pointer trap #1 ; do gemdos trap move.l saveA7, A7 ; restore stack pointer move.l traprtn, -(A7) ; put return address back rts ; return ; ; long _bios(function, [parameter, ...]) ; int function; ; __bios: move.l (A7)+, traprtn ; save return address move.l A7, saveA7 ; save stack pointer trap #13 ; do bios trap move.l saveA7, A7 ; restore stack pointer move.l traprtn, -(A7) ; put return address back rts ; return ; ; long _xbios(function, [parameter, ...]) ; int function; ; __xbios: move.l (A7)+, traprtn ; save return address move.l A7, saveA7 ; save stack pointer trap #14 ; do xbios trap move.l saveA7, A7 ; restore stack pointer move.l traprtn, -(A7) ; put return address back rts ; return bss even traprtn: ds.l 1 ; storage for return PC in trap hooks saveA7: ds.l 1 ; storage for stack pointer in traps
apratt@atari.UUCP (Allan Pratt) (01/10/90)
dmb@TIS.COM (David M. Baggett) writes: >I.e., adding *just* > Setscreen(-1L, -1L, 1); >to my process termination handler causes the handler to RTS to an >illegal instruction. Note that this call is #defined in ><osbind.h> and turns into > xbios(5, -1L, -1L, 1) >(i.e., it calls the xbios hook in dstart.o, provided with Sozobon). > >Saving the stack pointer before the trap and restoring it afterwards >fixes things. I don't believe it's a question of the stack pointer. When you return from the BIOS your sp is ALWAYS what it was before you went in. (How else could anything work?) I think it's a reentrancy problem. The OS hooks seem to use external storage, meaning they're non-reentrant. Worse, they all use the SAME external location, so in a given program, you can't call BIOS from BIOS, but you also can't call XBIOS from BIOS! (Study the flow of a BIOS call which calls XBIOS when both go through the same hook: the mainline calls BIOS, saving the return PC someplace. That BIOS code calls XBIOS, saving it's return PC IN THE SAME PLACE!) On the other hand, it shouldn't matter, since the Pterm call in question never returns. Hooks like this can be made reentrant by changing how they work: instead of this: move.l (sp)+,trapret ; save return PC trap #$x move.l trapret,-(sp) ; restore return PC rts you could use this: movem.l 4(sp),d0-d2/a0-a2 ; get 6 longs' worth of args movem.l d0-d2/a0-a2,-(sp) ; push them trap #$x add.w #24,sp rts This uses no external storage (and therefore is reentrant). The point is to give the trap the intended args without the hook's own return PC in the way. The first method pops the PC off and saves it, while the second method does it by copying the args into a new stack frame.
dmb@TIS.COM (David M. Baggett) (01/10/90)
Oops, I screwed up. As Allan Pratt and Dave Berger have pointed out, you can't call GEMDOS from within a process termination handler. So ignore the new _gemdos hook in my original posting. It most definitely will not work. The _bios and _xbios hooks are fine, though. Sorry 'bout that. Dave Baggett dmb@TIS.COM