How NOT to set supervisor mode!
Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team
How NOT to set supervisor mode!
So, I had this little routine, but I was getting strange memory corruption:
lea stack_top(pc),a0
move.l a0,-(sp)
move.w #$20,-(sp)
trap #1
addq.l #6,sp
It's the familiar routine I've seen in many sources.
But upon further inspection in the debugger, it appears it's wrong. The final addq.l #6,sp should be omitted. Upon returning from the trap, stack pointer is exactly where you set it.
Somehow, all these years, I've used that risky addq.l routine without ever having a problem. Maybe this is common knowledge, but it seems like it could be commoner!
So the revised routine is simply:
lea stack_top(pc),a0
move.l a0,-(sp)
move.w #$20,-(sp)
trap #1
Now, a question... in some sources, I've seen people passing 0 as the stack_top value. What's up with that? Wouldn't that put the stack in the TOS ROM? Does a value 0 have a special meaning? Even more confusingly, some sources push only a zero word as stack_top, not a longword.
lea stack_top(pc),a0
move.l a0,-(sp)
move.w #$20,-(sp)
trap #1
addq.l #6,sp
It's the familiar routine I've seen in many sources.
But upon further inspection in the debugger, it appears it's wrong. The final addq.l #6,sp should be omitted. Upon returning from the trap, stack pointer is exactly where you set it.
Somehow, all these years, I've used that risky addq.l routine without ever having a problem. Maybe this is common knowledge, but it seems like it could be commoner!
So the revised routine is simply:
lea stack_top(pc),a0
move.l a0,-(sp)
move.w #$20,-(sp)
trap #1
Now, a question... in some sources, I've seen people passing 0 as the stack_top value. What's up with that? Wouldn't that put the stack in the TOS ROM? Does a value 0 have a special meaning? Even more confusingly, some sources push only a zero word as stack_top, not a longword.
Re: How NOT to set supervisor mode!
I am afraid that
More explanation here: http://toshyp.atari.org/en/00500e.html#Super
Sounds like an RTFM problem
- your "solution" is not a solution at all as it leaves garbage on the stack
- your "solution" just hides the real problem somewhere outside the code snippet you provided
Code: Select all
pea stack
move.w #32,-(sp)
trap #1
addq.l #6,sp
Sounds like an RTFM problem

-
- Hardware Guru
- Posts: 2269
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: How NOT to set supervisor mode!
I guess you're both missing the point: SV is set by the stack value == 0L. :) (and then call, within the supervisor mode, the trap with the original SP -- that way you wont trash the original content placed on the stack).
Re: How NOT to set supervisor mode!
Hi,
Here is an example:
But if you just have a little routine to execute in supervisor mode, the XBIOS is better with SUPEXEC:
Guillaume.
Here is an example:
Code: Select all
.. here in USER mode...
clr.l -(sp) ; 0 to go to supervisor
move #32,-(sp)
trap #1
addq.l #6,sp ; returns in D0 the old pointer
... here in supervisor mode ...
move.l d0,-(sp) ; set the old pointer
move #32,-(sp)
trap #1
addq.l #6,sp
... back in USER mode ....
Code: Select all
... here in USER
pea myroutine
move #38,-(sp)
trap #14 ; executes myroutine in supervisor
addq.l #6 sp ; and comes back here
.. always in user....
myroutine:
... my instructions in supervisor...
... saving registers that could be modified...
RTS
- Zorro 2
- Administrator
- Posts: 2226
- Joined: Tue May 21, 2002 12:44 pm
- Location: Saint Cloud (France)
- Contact:
Re: How NOT to set supervisor mode!
And you can detect if it's used in a program relocated
Code: Select all
move SR,d0 ; Test supervisor mode
btst #13,d0 ; Specialy for relocation
bne.s mode_super_yet ; programs
move.l 4(sp),a5 ; Address to basepage
move.l $0c(a5),d0 ; Length of TEXT segment
add.l $14(a5),d0 ; Length of DATA segment
add.l $1c(a5),d0 ; Length of BSS segment
add.l #$1000,d0 ; Length of stackpointer
add.l #$100,d0 ; Length of basepage
move.l a5,d1 ; Address to basepage
add.l d0,d1 ; End of program
and.l #-2,d1 ; Make address even
move.l d1,sp ; New stackspace
move.l d0,-(sp) ; Mshrink()
move.l a5,-(sp) ;
move.w d0,-(sp) ;
move.w #$4a,-(sp) ;
trap #1 ;
lea 12(sp),sp ;
clr.l -(sp) ; Supervisor mode
move.w #32,-(sp) ;
trap #1 ;
addq.l #6,sp ;
mode_super_yet:
Member of NoExtra Team
Re: How NOT to set supervisor mode!
I'm afraid I'm still confused. I originally had the above snippet, but it *definitely* failed. The stack pointer was erroneously moved up by 6, overwriting variables that I had placed after the stack.Arne wrote:I am afraid thatThe Atari Profibuch shows this snippet:
- your "solution" is not a solution at all as it leaves garbage on the stack
- your "solution" just hides the real problem somewhere outside the code snippet you provided
Code: Select all
pea stack move.w #32,-(sp) trap #1 addq.l #6,sp
For example, here is the program state just prior to calling the trap:
You can see 000BBFEE has been pushed to the user stack. 000BBFEE is the location I intended to use as the SSP.
Then, immediately after calling the trap:
SSP has now taken on the value 000BBFEE exactly - not displaced by 6. If I were to do addq.l #6,sp then it would move up to 000BBFF4 - overwriting the contents of memory beyond the stack. This is the problem I was having.
Is the problem something to do with returning to user mode at program exit? I can't say I've had any problems with exiting cleanly, but I've not traced that part. I assume the OS restores its old SSP at program exit?
I haven't tried passing 0 as the stack value. It could well behave differently then, requiring adding 6.Moulinaie wrote:Code: Select all
.. here in USER mode... clr.l -(sp) ; 0 to go to supervisor move #32,-(sp) trap #1 addq.l #6,sp ; returns in D0 the old pointer ... here in supervisor mode ... move.l d0,-(sp) ; set the old pointer move #32,-(sp) trap #1 addq.l #6,sp ... back in USER mode ....
If 0 keeps the existing stack pointer unchanged, is it necessary to call supervisor mode a second time with d0?
I'm not sure I want to leave the stack pointer unchanged, because I don't know how big the supervisor stack is. It seems to be in low memory - 37CA in the example above.
You do not have the required permissions to view the files attached to this post.
Re: How NOT to set supervisor mode!
I must confess I've never tried setting the SSP through the supervisor trap. If you want to change the SSP when in supervisor mode it's really simple
move.l #stack,sp
(Do note this uses self modifying code ... lazy 68000 demo coders ...
Also, _memtop is of course set someplace else depending on the phases of the moon)
/Troed

Code: Select all
pea 0
move.w #$20,-(a7)
trap #1
addq.l #6,a7
move.l d0,_save_usp+2
move.l _memtop,a0
suba.l #$1000,a0
move.l a0,a7 * set up stack
_save_usp pea 0
move.w #$20,-(a7)
trap #1
addq.l #6,a7

/Troed
Re: How NOT to set supervisor mode!
I just did a trace with the following code:
clr.l -(sp)
move.w #$20,-(sp)
trap #1
addq.l #6,sp
And with this code, the +6 is definitely necessary - because the ssp will take on the value of the usp. So, it seems the general rule is that when passing a new stack value, the add should be omitted. But when passing 0, it should be included.
What I'm not sure about is whether TOS restores the old SSP upon program exit. The fact it returns the old SSP in d0 suggests that you might need to do it manually. But I haven't been doing that, and so far no crashes.
clr.l -(sp)
move.w #$20,-(sp)
trap #1
addq.l #6,sp
And with this code, the +6 is definitely necessary - because the ssp will take on the value of the usp. So, it seems the general rule is that when passing a new stack value, the add should be omitted. But when passing 0, it should be included.
What I'm not sure about is whether TOS restores the old SSP upon program exit. The fact it returns the old SSP in d0 suggests that you might need to do it manually. But I haven't been doing that, and so far no crashes.
-
- Hardware Guru
- Posts: 2269
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: How NOT to set supervisor mode!
Wrong. You still must addq.l #6, sp when returning from the supervisor. See above for examples.Foxie wrote:So, it seems the general rule is that when passing a new stack value, the add should be omitted.
Re: How NOT to set supervisor mode!
But this really doesn't appear to be the case. If you add 6 to the stack pointer (when you specified your own stack), you *will* overwrite memory beyond the stack. You can see what happens in the screenshots I posted above. Adding 6 would cause SSP to equal BBFF4 - which is exactly where my variables are stored.mikro wrote: Wrong. You still must addq.l #6, sp when returning from the supervisor. See above for examples.
Correcting the supervisor stack pointer by 6 serves no useful function, because the initial parameters were pushed to the user stack. If anything, it should be the user stack pointer corrected by 6. But this doesn't appear to be necessary because the user stack ceases to exist on program exit anyway.
This only applies when you're passing your own stack pointer, unrelated to the user stack. If you pass 0 as the stack pointer, then correction is absolutely necessary. The USP and SSP are one and the same then.
-
- Hardware Guru
- Posts: 2269
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: How NOT to set supervisor mode!
Well, try it by yourself -- enter the supervisor with clr.l -(sp), save the old user stack and return with move.l user_stack,-(sp) back to the user mode. You'll clearly see six bytes off. Maybe you haven't noticed I'm not talking about setting supervisor stack but exiting from the supervisor instead as reply to your claim "So, it seems the general rule is that when passing a new stack value, the add should be omitted."
Re: How NOT to set supervisor mode!
Hmm, I've never tried to exit from super mode besides just exiting the program. If you push 6 bytes to the user stack and go into super mode, it stands to reason that those 6 bytes would still be there on the user stack (but not the supervisor stack, unless you make them the same with clr.l -(sp)). So if you come out of super mode, then you'd need to pop them. But if you're just going to exit directly from super mode with term, then the USP probably doesn't need to be adjusted.mikro wrote:Well, try it by yourself -- enter the supervisor with clr.l -(sp), save the old user stack and return with move.l user_stack,-(sp) back to the user mode. You'll clearly see six bytes off. Maybe you haven't noticed I'm not talking about setting supervisor stack but exiting from the supervisor instead as reply to your claim "So, it seems the general rule is that when passing a new stack value, the add should be omitted."
It would make sense for TOS to adjust the stack upon returning to user mode. It would undo the pushing of the initial bytes used to enter super mode.