delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/09/08/06:45:05

From: Leif Leonhardy <leif AT dtcs DOT de>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: __dpmi_simulate_real_mode_procedure_retf[stack](): Links to bug fixes? FAQ?
Date: Sat, 08 Sep 2001 12:36:42 +0200
Organization: delta t Computerservice
Lines: 254
Message-ID: <3B99F4BA.D0753BF0@dtcs.de>
References: <3B9993B7 DOT 7673E4B7 AT dtcs DOT de> <3405-Sat08Sep2001095723+0300-eliz AT is DOT elta DOT co DOT il>
NNTP-Posting-Host: pd9e0e1c2.dip0.t-ipconnect.de
Mime-Version: 1.0
X-Trace: news.online.de 999945327 28875 217.224.225.194 (8 Sep 2001 10:35:27 GMT)
X-Complaints-To: abuse AT online DOT de
NNTP-Posting-Date: 8 Sep 2001 10:35:27 GMT
Cc: leif AT dtcs DOT de
X-Mailer: Mozilla 4.01 [de] (Win95; I)
X-Priority: 3 (Normal)
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

Eli Zaretskii schrieb:
> 
> > From: Leif Leonhardy <leif AT dtcs DOT de>
> > Newsgroups: comp.os.msdos.djgpp
> > Date: Sat, 08 Sep 2001 05:42:47 +0200
> >
> > PROBLEM: passing arguments to real mode procedures via the (which?!)
> >          stack
> >        I tried BOTH __dpmi_simulate_real_mode_procedure_retf_stack()
> >        AND __dpmi_simulate_real_mode_procedure_retf() setting up
> >        the stack (regs.x.ss, regs.x.sp) by myself - with exactly
> >        the same results.
> >
> > Few minutes ago ;-) I was happy to find a patch for d0301_s.S (from
> > about a year ago), not immediately realizing that this patch wouldn't
> > solve my problem because the function without the extra stack parame-
> > ters behaves exactly (?) the same :-(
> 
> Sorry, I don't understand this.  d0301_s.S, as shipped with DJGPP
> v2.03 indeed has a bug (all older versions also had a bug, albeit a
> different and more grave one).  But what do you mean by the last
> sentence above?  What does ``without the extra stack parameters''
> mean?
There are two functions,
__dpmi_simulate_real_mode_function_retf(__dpmi_regs r)
and __dpmi_simulate_real_mode_function_retf_stack(__dpmi_regs r,int
num_stack_words,short *stack),
of which the latter does just a little bit more than the first, namely
copying stack words supplied in the (protected-mode) array stack onto
the
(DPMI clients) protected-mode stack. Both functions use _the same_
DPMI int (0301h).

The DPMI function 0301h now again copies stack words from the protected-
mode stack to the real-mode stack. The number of words to copy is
specified by the _processor register_ %ecx (and _not_ regs.x.cx),
while the real-mode stack is specified through regs.x.ss:regs.x.sp.
If SS:SP in the regs structure is zero, the DPMI host allocates
(or reuses) a real-mode (conventional memory) stack area.
[Believe me, I try to check all sources and to fix the bug myself before 
I post a 'all bad-nothing works'.]

Since __dpmi_simulate_real_mode_function_retf() clears %ecx, nothing
is copied in that case. None of the two djgpp functions deals with
the stack specified in the regs structure (zero or not), this is
solely handled by the DPMI host.

The posted patch applies only to d0301_s.S (...retf_stack()),
not to d0301.S (...retf()); the fixed bug was exactly in the
stack-copying,
so if there really is a bug, it must be in both functions, because
their behaviour is identical (see below).

> Anyway, I append below the fixed source of d0301_s.S.  I think it
> should solve your problem, although it's a bit hard to know, what with
> all the text you wrote without showing a single code line or
> explaining what exactly doesn't work ;-) (It's possible that the patch
> you saw was for an earlier version of the function, i.e. for e a
> different bug.)
This is not the case. Sorry for not providing my code; this is due to
its uglyness caused by debugging code and
__the_really_very_long_function_names ;-)

I first tried to work-around the known bug by using the 'shorter'
function,
which avoids the copying in question, but both functions fail in the
same
manner, so the bug must be elsewhere (ok, possibly in my code).
> 
> It's still there because no new versions of DJGPP were released since
> the bug was discovered.  The patches are published precisely for that
> reason: so people who cannot wait for the next official release could
> patch their libraries and go on with their coding.
Is there a diff-central? I found it hard to track articles dealing with
these (or the _go32-)functions posted in 1995, 1997, 1999 and later.

> Finally, your ``which stack?'' question seems to indicate that you are
> unsure how to pass the data on stack to these functions.
The "which %&$*:! stack?" should read: "I am sure the real-mode
procedure
is using *some* stack, but not the one I've specified nor does this
stack
in any way relate to (the values of) the protected-mode stack."

> Assuming you use __dpmi_simulate_real_mode_procedure_retf_stack (which 
> is what you _should_ use), ...
The DPMI spec limits the size of the stack provided in case no stack is
explicitly specified by the caller (SS:SP==0), so the _safe_ way
should be to allocate one - big enough for the specific function(s).

And, if we do that, the ...retf_stack() function is completely super-
fluous because we can poke() (or movedata()) the data directly onto
the real-mode stack in conventional memory, saving one or two times
copying.
 
> If this still doesn't help, please post the fragment of your code
> which invokes __dpmi_simulate_real_mode_procedure_retf_stack to call
> the ASPI manager.
Ok, but I will abstract from ASPI manager, since my problem can be
shown (much?) simpler:

------8<----------------8<------cut-here-------8<---------8<------------
/* bug.c -- test GO32's
__dpmi_simulate_real_mode_procedure_retf[_stack]()
*/

#include <stdio.h>
#include <dpmi.h>
#include <sys/farptr.h>

int test_RM_call()
{ __dpmi_regs regs;
  int the_RM_address_to_call;   /* high word: SEG, low word OFFSET */
  short words_to_put_onto_RM_stack[2];
  int conv_mem_seg;             /* RM segment for conventional memory
area */
  int conv_mem_sel;             /* PM selector for conventional memory
area */
  unsigned conv_mem_size;       /* size of conv. mem. area in bytes */
  unsigned conv_mem_paras;      /* size of conv. mem. area in paragraphs
*/

  conv_mem_size=0x200;          /* 512 bytes */
  conv_mem_paras=(conv_mem_size+15)/16; /* round up to paragraph
boundary */

  /* Allocate conv. mem. area: */
 
if((conv_mem_seg=__dpmi_allocate_dos_memory(conv_mem_paras,&conv_mem_sel))
    ==-1)
  {
    printf("__dpmi_allocate_dos_memory() failed!\n");
    return 1;
  }
  /* Should possibly clear allocated area... (NYI) */

  /* Put RM code to call into this area: */
  _farpokeb(conv_mem_sel,0,0xB8);       /* B8 11 47 = mov ax,4711h */
  _farpokeb(conv_mem_sel,1,0x11);
  _farpokeb(conv_mem_sel,2,0x47);
  _farpokeb(conv_mem_sel,3,0xCB);       /* CB = retf */

  /* Address to call is first byte of allocated area: */
  the_RM_address_to_call=(conv_mem_seg<<16)|(0/*conv_mem_off*/);

  /* Now (try to) call it: */
  regs.x.flags=0;
  regs.x.ss=0;          /* DPMI function has to provide stack */
  regs.x.sp=0;
  regs.x.cs=the_RM_address_to_call>>16;         /* segment of address */
  regs.x.ip=the_RM_address_to_call&0xffff;      /* offset of address */
  if(__dpmi_simulate_real_mode_procedure_retf(&regs)!=0)
  {
    printf("__dpmi_simulate_real_mode_procedure_retf() failed!\n");
    return 2;
  }
  printf("Real mode function returned, AX=%hXh\n",regs.x.ax);

  /* Modify function code such that first parameter on stack will be */
  /* returned in AX (second in BX if specified): */
  _farpokeb(conv_mem_sel,0,0x5B);       /* 5B = pop bx ; return address
*/
  _farpokeb(conv_mem_sel,1,0x58);       /* 58 = pop ax ; first parameter
*/
  _farpokeb(conv_mem_sel,2,0x50);       /* 50 = push ax ; first
parameter */
  _farpokeb(conv_mem_sel,3,0x53);       /* 53 = push bx ; return address
*/
  _farpokeb(conv_mem_sel,4,0xCB);       /* CB = retf */

  /* Now call it with parameter(s) on the stack: */
  words_to_put_onto_RM_stack[0]=0xAFFE; /* Affe: German for "ape" */
  words_to_put_onto_RM_stack[1]=0xDEAD;
  regs.x.flags=0;
  regs.x.ss=0;          /* DPMI function has to provide stack */
  regs.x.sp=0;
  regs.x.cs=the_RM_address_to_call>>16;         /* segment of address */
  regs.x.ip=the_RM_address_to_call&0xffff;      /* offset of address */
  if(__dpmi_simulate_real_mode_procedure_retf_stack(&regs,
    2 /* words */,
    words_to_put_onto_RM_stack)!=0)
  {
    printf("__dpmi_simulate_real_mode_procedure_retf_stack()
failed!\n");
    return 3;
  }
  printf("Real mode function returned, AX=%hXh, BX=%hXh\n",
    regs.x.ax,regs.x.bx);

  printf("Now setting up RM stack by myself...\n");
  words_to_put_onto_RM_stack[0]=0x0815;
  words_to_put_onto_RM_stack[1]=0x4711;
  regs.x.ss=conv_mem_seg;
  regs.x.sp=conv_mem_size-4;    /* stacks grows from ..._size to 0 */
  _farpokew(conv_mem_sel,conv_mem_size-2,words_to_put_onto_RM_stack[0]);
  _farpokew(conv_mem_sel,conv_mem_size-4,words_to_put_onto_RM_stack[1]);

  /* Now call it with parameter(s) on my stack: */
  regs.x.flags=0;
  regs.x.cs=the_RM_address_to_call>>16;         /* segment of address */
  regs.x.ip=the_RM_address_to_call&0xffff;      /* offset of address */
  regs.x.ax=regs.x.bx=0; /* clear to see that function actually changed
it */
  if(__dpmi_simulate_real_mode_procedure_retf(&regs)!=0)
  {
    printf("__dpmi_simulate_real_mode_procedure_retf() failed!\n");
    return;
  }
  printf("Real mode function returned, AX=%hXh, BX=%hXh\n",
    regs.x.ax,regs.x.bx);

  return 0;
}

main()
{
  return test_RM_call();
}
------8<----------------8<------cut-here-------8<---------8<------------
F:\GCC\go33\dtcs\aspi>gcc -o bug bug.c

F:\GCC\go33\dtcs\aspi>bug
Real mode function returned, AX=4711h
Real mode function returned, AX=FCB2h, BX=2FF7h
Now setting up RM stack by myself...
Real mode function returned, AX=FCB2h, BX=2FF7h

F:\GCC\go33\dtcs\aspi>
------8<----------------8<------cut-here-------8<---------8<------------
In a few words:
	- I construct the code to be called in a real-mode buffer
	  to assure that the function (address) is actually called
	  and this call works (AX=4711h, set by called function)
        - Then I call a modified function (same address) with two
          parameters via ..._retf_stack(), the passed parameters
	  should be returned in AX and BX
        - Finally I set up the real-mode stack in the same buffer,
	  but on the other end (512 bytes total are enough here)
	  Again, the passed parameters should be returned in AX
	  and BX

As you can see, both calls result in the _same_, unexpected values.

Would be nice to hear you can observe the same (the unexpected
values will probably differ, but be the same for both calls).

Nicer to hear would be "Idiot, typo at line...", or 
"alloc_brain() failed", though I RTFMs

[And if someone has a free ASPI library working, this would be fine
 to hear, too.]

Leif
<flame> tags omitted in last post, sorry.

- Raw text -


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