How NOT to set supervisor mode!

All 680x0 related coding posts in this section please.

Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team

User avatar
Foxie
Captain Atari
Captain Atari
Posts: 354
Joined: Wed Feb 03, 2016 7:12 pm

How NOT to set supervisor mode!

Postby Foxie » Sat Jan 06, 2018 3:39 am

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.

User avatar
Arne
Captain Atari
Captain Atari
Posts: 443
Joined: Thu Nov 01, 2007 10:01 am

Re: How NOT to set supervisor mode!

Postby Arne » Sat Jan 06, 2018 7:22 am

I am afraid that
  • 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
The Atari Profibuch shows this snippet:

Code: Select all

pea       stack
move.w    #32,-(sp)
trap      #1
addq.l    #6,sp


More explanation here: http://toshyp.atari.org/en/00500e.html#Super

Sounds like an RTFM problem :mrgreen:
Image

mikro
Atari God
Atari God
Posts: 1733
Joined: Sat Sep 10, 2005 11:11 am
Location: Kosice, Slovakia
Contact:

Re: How NOT to set supervisor mode!

Postby mikro » Sat Jan 06, 2018 9:37 am

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).

Moulinaie
Captain Atari
Captain Atari
Posts: 201
Joined: Wed Feb 01, 2012 9:34 pm

Re: How NOT to set supervisor mode!

Postby Moulinaie » Sat Jan 06, 2018 10:23 am

Hi,

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 ....


But if you just have a little routine to execute in supervisor mode, the XBIOS is better with SUPEXEC:

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


Guillaume.

User avatar
Zorro 2
Administrator
Administrator
Posts: 2198
Joined: Tue May 21, 2002 12:44 pm
Location: Saint Cloud (France)
Contact:

Re: How NOT to set supervisor mode!

Postby Zorro 2 » Sat Jan 06, 2018 1:13 pm

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

User avatar
Foxie
Captain Atari
Captain Atari
Posts: 354
Joined: Wed Feb 03, 2016 7:12 pm

Re: How NOT to set supervisor mode!

Postby Foxie » Sat Jan 06, 2018 5:38 pm

Arne wrote:I am afraid that
  • 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
The Atari Profibuch shows this snippet:

Code: Select all

pea       stack
move.w    #32,-(sp)
trap      #1
addq.l    #6,sp



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.

For example, here is the program state just prior to calling the trap:

1Screen Shot 2018-01-06 at 17.30.58.png


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:

2Screen Shot 2018-01-06 at 17.31.35.png


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?


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 ....



I haven't tried passing 0 as the stack value. It could well behave differently then, requiring adding 6.

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.

User avatar
troed
Atari God
Atari God
Posts: 1427
Joined: Mon Apr 30, 2012 6:20 pm
Location: Sweden

Re: How NOT to set supervisor mode!

Postby troed » Sat Jan 06, 2018 6:05 pm

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

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


(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

User avatar
Foxie
Captain Atari
Captain Atari
Posts: 354
Joined: Wed Feb 03, 2016 7:12 pm

Re: How NOT to set supervisor mode!

Postby Foxie » Sat Jan 06, 2018 7:24 pm

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.

mikro
Atari God
Atari God
Posts: 1733
Joined: Sat Sep 10, 2005 11:11 am
Location: Kosice, Slovakia
Contact:

Re: How NOT to set supervisor mode!

Postby mikro » Sat Jan 06, 2018 9:21 pm

Foxie wrote:So, it seems the general rule is that when passing a new stack value, the add should be omitted.

Wrong. You still must addq.l #6, sp when returning from the supervisor. See above for examples.

User avatar
Foxie
Captain Atari
Captain Atari
Posts: 354
Joined: Wed Feb 03, 2016 7:12 pm

Re: How NOT to set supervisor mode!

Postby Foxie » Sat Jan 06, 2018 9:54 pm

mikro wrote:Wrong. You still must addq.l #6, sp when returning from the supervisor. See above for examples.


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.

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.

mikro
Atari God
Atari God
Posts: 1733
Joined: Sat Sep 10, 2005 11:11 am
Location: Kosice, Slovakia
Contact:

Re: How NOT to set supervisor mode!

Postby mikro » Sat Jan 06, 2018 11:18 pm

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."

User avatar
Foxie
Captain Atari
Captain Atari
Posts: 354
Joined: Wed Feb 03, 2016 7:12 pm

Re: How NOT to set supervisor mode!

Postby Foxie » Sun Jan 07, 2018 1:04 am

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."


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.

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.


Social Media

     

Return to “680x0”

Who is online

Users browsing this forum: No registered users and 2 guests