www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/04/03/09:16:21

From: "A.Appleyard" <A DOT APPLEYARD AT fs2 DOT mt DOT umist DOT ac DOT uk>
To: DJGPP AT delorie DOT com
Date: Wed, 3 Apr 1996 15:07:00 GMT
Subject: Re: Odd happenings with an interrupt
Message-ID: <351FFC45EA@fs2.mt.umist.ac.uk>

  I have gcc-2.6.0 gas-2.3 libg++-2.6.0 1.12.maint2 binutils 2.4
  I may have tracked my interrupt funny to its lair:-

#include <stdio.h>
#include <std.h>
#include <pc.h>
#include <dos.h>
#include <dpmi.h>
#include <go32.h>
/*-----*/
#define uns unsigned
#define reg register
#define pk __attribute__((packed))
typedef uns long ul;
typedef uns short us;
typedef uns char byte;
#define Regs _go32_dpmi_registers
Regs R;
#define Int int86dpmi
/*-----*//* with thanks to Eli Zaretski */
/* Simulate a software interrupt from protected mode. Like int86() but calls
   DPMI services and so doesn't need DOS extender, only a DPMI server. */
int int86dpmi(int intno) {REGS r,s; Regs S; S=R;
S.x.ss=S.x.sp=0; /* DPMI server is to provide stack for interrupt call */
S.x.flags=0; /* he likeliest forgot to zero the flags */
/* I replaced the call of _go32_dpmi_simulate_int() by a copy of its body here*/
r.h.bl=intno; r.h.bh=0; r.x.cx=0; r.x.di=(int)&S;
if(intno==0x21 && S.x.ax==0x4b00) { /* call a child process */
      r.x.ax=0xff0a; int86(0x21,&r,&s);}
else {r.x.ax=0x0300; int86(0x31,&r,&s);}
R=S; return R.d.eax;}
/*-----*//* conventional memory:- */
class c_mem {public: _go32_dpmi_seginfo x;
inline c_mem(int nbytes){x.size=nbytes; _go32_dpmi_allocate_dos_memory(&x);};
inline segof(uns short&s,uns short&o){s=x.rm_segment; o=x.rm_offset;};
inline ~c_mem(){_go32_dpmi_free_dos_memory(&x);};};
/* typedef struct {uns long size, pm_offset;
      uns short pm_selector, rm_offset, rm_segment;} _go32_dpmi_seginfo; */;
/*-----*//* structure of the buffer returned by `AX=4f01, int10' */
typedef struct modeinfo {short modeattr pk; byte waattr,wbattr pk;
short wgran,wsize,waseg,wbseg pk; long farwposfn pk;
short bytesperline,wide,high pk;
byte cwide,chigh,nplanes,bitsperpixel,nbanks,memmod,banksize,npages,res1,
redsize,redpos,greensize,greenpos,bluesize,bluepos,ressize,respos,dircolor pk;
void pr(FILE*F){fprintf(F," %4d %3d %3d %4d %4d %04x %04x %08lx \
%4d %4d %4d %3d %3d %3d %3d %3d %4s %3d %3d %3d \
%3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
  modeattr,waattr,wbattr,wgran,wsize,(uns short)waseg,(uns short)wbseg,
  farwposfn,bytesperline,wide,high,cwide,chigh,nplanes,bitsperpixel,nbanks,
    ((char*[]){"text","cga","hgc","16cl","pkpx","s256","dirc","yuv"})[memmod],
    banksize,npages,res1,redsize,redpos,greensize,greenpos,bluesize,bluepos,
    ressize,respos,dircolor);};
};
/*-----*/
FILE*M;
/*-----*/
int getinfo(int mode){c_mem buf(256); modeinfo m;
R.x.ax=0x4f01; R.x.cx=mode; buf.segof(R.x.es,R.x.di); Int(0x10);
if((R.x.ax&255)!=0x4f) return 0; // if(R.x.ax&0xff00) return 0;
dosmemget(buf.x.rm_segment*16+buf.x.rm_offset,40,&m);
if(!(m.modeattr&1)) return 0;
/* fprintf(M,"%3x:",mode); m.pr(M); */ return 1;}
/*-----*/
main(){M=fopen("t$$mode4","w"); int i; for(i=0;i<128;i++) getinfo(i); fclose(M);
for(i=0;i<128;i++) if(getinfo(i)) ;//printf("mode %04x exists\n",i);
int mode; FILE*F=fopen("t$qaz","w"); printf("mode?"); scanf("%x",&mode);
fclose(F);}

As quoted, this program fails "Divide error" during the interrupt routine and
exits to the DOS prompt leaving the stacks funny. But if I remove
`for(i=0;i<128;i++) getinfo(i); fclose(M);', the program runs OK. Each call of
the function getinfo should _go32_dpmi_allocate_dos_memory 256 bytes of
conventional memory on entry (by the class c_mem constructor), and release it
all on exit (by the class c_mem destructor). It seems that doing that too many
times in one program run messes up the conventional memory heap. Why is that?
Surely getting and then releasing 256 bytes of conventional memory should
leave the conventional memory and all pointers to it as they were before?

- Raw text -


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