www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2002/02/22/08:02:20

X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-bounces using -f
From: "MarKol" <markol4 AT wp DOT pl>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: DS and ESP
Date: Thu, 21 Feb 2002 21:25:51 +0100
Organization: tp.internet - http://www.tpi.pl/
Lines: 228
Message-ID: <a55f0s$dom$1@news.tpi.pl>
References: <a4rfgu$sbg$1 AT news DOT tpi DOT pl> <968-Mon18Feb2002212153+0200-eliz AT is DOT elta DOT co DOT il>
NNTP-Posting-Host: seazone.gda.pl
Mime-Version: 1.0
X-Trace: news.tpi.pl 1014382429 14102 195.117.175.253 (22 Feb 2002 12:53:49 GMT)
X-Complaints-To: usenet AT tpi DOT pl
NNTP-Posting-Date: Fri, 22 Feb 2002 12:53:49 +0000 (UTC)
X-Priority: 3
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
X-Newsreader: Microsoft Outlook Express 5.50.4133.2400
X-MSMail-Priority: Normal
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

Hi

: Użytkownik "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il> napisał w wiadomo¶ci
: >
: >    +I wonder if gcc, doesn't change ds?
:
: Code generated by GCC assumes DS = SS = ES.
:
: >     I think that there no need to change to change ds for compiler
but
: >     I'm not sure about this.
: >    +Are DJGPP's libc function conform to his rule?
: >     In other words I wonder in there is some piece of code in
DJGPP's libc
: >     which may be executed during normal program flow (not loading
: >     or ending),  and changes ds selector (and it is possible
: >     to accept HW interrupt by CPU at ehis moment)?
:
: DS may become invalid if a signal happens, like if you press Ctrl-C
: or run with timers.  The library provides a special alias selector,
: __djgpp_ds_alias, which is always valid and spans the same memory
: region as the selector normally loaded into DS.

Yes, but how do I load this __djgpp_ds_alias selector when my ds
is invalid??

But I think this will work
and I'm able to load proper ds segment in my wrapper routine.
I can put something like this in my wrapper:

.
.
.
mov  ax, 0
mov  ds, ax
.
.
.

When program is running I can get my ds segment selector (_my_ds()
AFAIR)
and then modify code shown above (via DS, since DS=SS=CS),
replacing zero with proper data segment selector returned by _my_ds().
I think this will definitely solve problems with valid ds segment when
my interrupt wrapper is called.

:
: >  b) similar problem is about esp (I belive that ss is valid ).
: >     My stub routine assumes that valid program data on stack are
: >     pointed by esp and higher values.
:
: The interrupt handler is called on a special locked stack provided by
: the DPMI host.  Is this the stack you are talking about?  If so, it
: will never clash with the application's stack.
:

No, I'm talking about user's stack. I create alias descriptor for
user's stack (with changed DPL to 0, since I cannot reload
ss (when executing on ring0) with selector pointing to ring 3
descriptor).
I'm doing this because I want to satisfy GCC about CS=DS=SS.

0. I assume that no page fault occurs (all required pages are present).
   (this can be easily achieved, under CWSDPMI and plain DOS)

1. I put my interrupt gate directly in IDT and DPMI host
   doesn't have chance to catch such interrupt.

2. I case when ring is changed selector and stack pointer is taken from
   TSS, and this is internal CWSDPMI stack.

3. In the begining of my interrupt wrapper stack looks like this
   (when ring switch occurs)

          |--------|
 [esp+16] |   SS   |        ; ring 3 ss
          |--------|
 [esp+12] |  ESP   |        ; ring 3 esp
          |--------|
 [esp+8]  | EFLAGS |        ;
          |--------|
 [esp+4]  |   CS   |        ;
          |--------|
 [esp]    |  EIP   |        ;
          |--------|
          |        |

4. Oh no, my english is poor. Maybe I'll show code which
   is doing what I'm writing of.

This is unmodified version (assumes that ds is proper) but seems to work
fine.
I'll implement trick with changing ds as written above.

asm_int_wrapper:
         pushad
         push   ds
         push   es

         ;
         ;
         ;
         mov   ax,   cs
         mov   ecx,  [esp+4+40]
         xor   ax,   cx
         and   ax,   0x3
         jz    .@ring_not_changed

         ;
         ; ring changed
         ;
         mov   eax,  [esp+16+40]       ; user's stack selector
         mov   edi,  [esp+12+40]       ; user's stack pointer
         mov   es,   ax
         xor   eax,  eax
         mov   ax,   ss

         ;
         ; Here is important that there is no user's data on stack below
         ; esp!
         ; write our current ss:esp on user's stack
         ;
         mov   [es:edi-4],   eax
         mov   [es:edi-8],   esp


         ;
         ; switch to user's stack
         ;
         mov   edx,  [esp+12+40]
         mov   eax,  [stack_r0selector]
         push  eax
         sub   edx,  8                 ; lower stack pointer since
                                       ; there is stored our ss:esp
         push  edx
         lss   esp,  [esp]
         ;
         ; stack switched
         ;

         ;
         ; load user's service routine address
         ;
         mov   eax,  [user_c_routine00]

         ;
         ; execute user's routine (may be written completely in C,
because DS=SS=CS)
         ;
         call  eax

         ;
         ; switch back to DPMI stack
         ;
         lss   esp,  [esp]

         jmp   .@int_exit_code


.@ring_not_changed:
         mov   eax,  [user_c_routine00]
         call  eax

.@int_exit_code:

         ;
         ; send EOI to 8259A
         ;
         mov   al,   0x0B
         out   0xA0, al
         in    al,   0xA0
         test  al,   0xff
         jz    .@eoi2master_only

         mov   al,   0x20
         out   0xA0, al
.@eoi2master_only:
         mov   al,   0x20
         out   0x20, al

         pop    es
         pop    ds
         popad

         iretd

Of course I can allocate some space in my data segment and use this
allocated buffer as the user stack when C service routine is
called (CS=DS=SS would be satisfied) but using existing user stack
looks more elegant ;-).

So if somebody is sure that esp is always valid please, let me know
about it.

: >     Anything below esp is not
: >     important for the program. But I've seen codes like this
: >     (simple but ilustrates problem accessing stack segment below
esp,
: >      maybe programmer thought that nothing wrong can happen):
: >
: >     mov   [esp-4],    eax
: >     shl   eax,        cl
: >     add   [edi],      eax
: >     mov   eax,        [esp-4]
: >
: >     If HW interrupt will be accepted between eax is restored there
: >     are valid program data on the stack below esp. My asm stub uses
: >     user stack below esp, and assumes there is no valid
: >     user data below esp (it uses 8 bytes for ss and esp)
:
: It is IMHO a very bad idea for the interrupt handler to use the
: application stack.  Especially since the selector loaded into SS can
: become invalid exactly like DS.

Maybe you're right, but:

I'd like to write service routines in C. You said that GCC assumes
CS=DS=SS, so how can I write my routine in C when I'm operating
on stack provided by DPMI??

Best regards,
--
  /     |_|_|_|_|     void identification(){               \
 /       |mov e|        printf("   Marek  Kolacz  ");       \
||       |cld  |        printf("   markol4 AT wp DOT pl  ");       ||
 \       |movsd|      }                                     /
  \_____/_______\__________________________________________/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019