delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/01/20/14:06:47

From: Martin Str|mberg <ams AT ludd DOT luth DOT se>
Message-Id: <200101201906.UAA03921@father.ludd.luth.se>
Subject: Debugging on 386
To: djgpp-workers AT delorie DOT com (DJGPP-WORKERS)
Date: Sat, 20 Jan 2001 20:06:20 +0100 (MET)
X-Mailer: ELM [version 2.4ME+ PL54 (25)]
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

Two questions.

1. While hacking on a program to check which of the INT21 calls are
supported, I needed to debug it on my 386 (as it hangs on it). The
program do not use any floating point (as far as I can tell). However
there are floating points signals delivered while running in
gdb. Perhaps gdb is using floating point and is confused? Or why are
floating point signals coming in?

Earlier it was said that debugging floating point program on a
387-less platform wasn't doable. Now the FAQ says (section 12.10) it
should work. Alas it doesn't.

Program compiled with "gcc -O2 -g -Wall prog.c -o prog".

"gdb --version":
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "i386-pc-msdosdjgpp".

My gdb session. My input starts with "->":
-> br main
-> r
Starting program: f:/hackery/stat/new_stat/analyse_.exe

Program received signal SIGEMT, Emulation trap.
0x5535 in _control87 ()
-> c
Program received signal SIGEMT, Emulation trap.
0x554f in _control87 ()
-> c
Breakpoint 1...
-> n
Exiting due to signal SIGFPE
Coprocessor Error at eip=00001a64, x87 status=
Program received signal SIGEMT, Emulation trap.
0x9611 in _status87 ()
-> n
Single stepping until exit from function _status87,
which has no line number information.
Exiting due to signal SIGFPE
Coprocessor Error at eip=00001a64, x87 status=
Program received signal SIGEMT, Emulation trap.
0x9611 in _status87 ()
-> c
Continuing.
00c1
eax=000000c1 ebx=00000010 ecx=00000000 edx=000473a0 esi=00000000
edi=000100e7
ebp=0008fefc esp=0008fec4
program=F:\HACKERY\STAT\NEW_STAT\ANALYSE_.EXE
cs: sel=00e7  base=10270000  limit=0009ffff
ds: sel=00ef  base=10270000  limit=0009ffff
es: sel=00ef  base=10270000  limit=0009ffff
fs: sel=00df  base=000473a0  limit=00003fff
gs: sel=00ff  base=00000000  limit=0010ffff
ss: sel=00ef  base=10270000  limit=0009ffff
App stack: [000901bc..000101bc]  Exceptn stack: [00010120..0000e1e0]

Call frame traceback EIPs:
  0x00009616 __status87+6
  0x00004d13 ___djgpp_traceback_exit+159
  0x00004da0 _raise+104
  0x00002c3a _fde_split+270
  0x00004daa _raise+114
  0x00004e07 ___djgpp_exception_processor+35
  0x00000001 0x1
  0x00003368 ___crt1_startup+204

Program exited with code 0377.
(gdb) q

F:\HACKERY\STAT\NEW_STAT>symify  -o k:/analyse_.txt analyse_.exe

Ideas?

Another little bug: N.B. the line after SIGFPE where "status=". I
suspect the line "00c1" after my last "c" is supposed to be output
earlier.


2. If I #define OFFS to 1024 in my program, it hangs (both on DOZE
6.22 and WINDOZE 98) after printing out the results from the first
call to AX=0x7303 (and funny things start to appear at top of the
screen). Isn't the transfer buffer at least 2kiB? Or is there some
other bug somewhere that I don't see?


Right,

						MartinS

----- Program starts. -----
#include <libc/stubs.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <dpmi.h>
#include <go32.h>
#include <dos.h>
#include <libc/farptrgs.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/vfs.h>
#include <libc/dosio.h>

/* Returns: 1 == OK, successful setting of variables.
            0 == no cdrom found, variables unchanged. */
static int
use_AX0x1510( int drive_number, long *blocks, long *free, long *bsize
)
{
  __dpmi_regs regs;

  /* For a CD-ROM drive, Int 21h/AX=3600h gives incorrect info.
     Use CD-ROM-specific calls if they are available.

     Int 2Fh/AX=1510h gives us a way of doing IOCTL with the
     CD-ROM device driver without knowing the name of the
     device (which is defined by the CONFIG.SYS line that
     installs the driver and can therefore be arbitrary).  */

  regs.x.ax = 0x150b; /* is this drive supported by CD-ROM driver? */
  regs.x.cx = drive_number;
  __dpmi_int(0x2f, &regs);
  if ((regs.x.flags & 1) == 0 && regs.x.bx == 0xadad && regs.x.ax != 0)
  {
    unsigned char request_header[0x14];
    int status, i = 2;

    /* Construct the request header for the CD-ROM device driver.  */
    memset (request_header, 0, sizeof request_header);
    request_header[0] = sizeof request_header;
    request_header[2] = 3; /* IOCTL READ command */
    *(unsigned short *)&request_header[0xe]  = __tb_offset;
    *(unsigned short *)&request_header[0x10] = __tb_segment;
    request_header[0x12] = 4; /* number of bytes to transfer */

    /* When the disk was just changed, we need to try twice.  */
    do {
      /* Put control block into the transfer buffer.  */
      _farpokeb (_dos_ds, __tb, 7); /* read sector size */
      _farpokeb (_dos_ds, __tb + 1, 0); /* cooked mode */
      _farpokew (_dos_ds, __tb + 2, 0); /* zero out the result field */

      /* Put request header into the transfer buffer and call the driver.  */
      dosmemput (request_header, sizeof (request_header), __tb + 4);
      regs.x.ax = 0x1510;
      regs.x.cx = drive_number;
      regs.x.es = __tb_segment;
      regs.x.bx = __tb_offset + 4;
      __dpmi_int (0x2f, &regs);
      status = _farpeekw (_dos_ds, __tb + 7);
      *bsize  = _farpeekw (_dos_ds, __tb + 2);
    } while (--i && (status & 0x800f) == 0x800f); /* disk changed */

    if (status == 0x100 && _farpeekw (_dos_ds, __tb + 4 + 0x12) == 4)
    {
      request_header[0x12] = 5; /* number of bytes to transfer */
      /* Put control block into the transfer buffer.  */
      _farpokeb (_dos_ds, __tb, 8); /* read volume size */
      _farpokel (_dos_ds, __tb + 1, 0); /* zero out the result field */

      /* Put request header into the transfer buffer and call the driver.  */
      dosmemput (request_header, sizeof (request_header), __tb + 5);
      regs.x.ax = 0x1510;
      regs.x.cx = drive_number;
      regs.x.es = __tb_segment;
      regs.x.bx = __tb_offset + 5;
      __dpmi_int (0x2f, &regs);
      if (_farpeekw (_dos_ds, __tb + 8) == 0x100
       && _farpeekw (_dos_ds, __tb + 5 + 0x12) == 5)
      {
        /* bsize has been set some lines above. */
        *free = 0;  /* no free space: cannot add data to CD-ROM */
        *blocks = _farpeekl (_dos_ds, __tb + 1);
        return 1;
      }
    }
  }

  return 0;
}

/* Returns: 0 == OK, successful setting of variables.
            -1 == call failed, errno set. */
static int
use_AH0x36( int drive_number, long *blocks, long *free, long *bsize )
{
  __dpmi_regs regs;

  /* Get free space info from DOS.  */
  regs.h.ah = 0x36;  /* DOS Get Free Disk Space call */
  regs.h.dl = drive_number + 1;
  __dpmi_int(0x21, &regs);

  /* Check for errors */
  if ((regs.x.ax & 0xffff) == 0xffff)
  {
    errno = ENODEV;
    return -1;
  }
  *bsize = regs.x.cx * regs.x.ax;
  *free = regs.x.bx;
  *blocks = regs.x.dx;

  return 0;
}


int main(int argc, char *argv[])
{
  __dpmi_regs regs;
  char tmp_path[ sizeof("C:/") + 1 ];
  int drive;
  int i;
  int ret;
  long blocks;
  long free;
  long bsize;

  if( argc != 2)
  {
    printf( "Run like this: '%s <letter_of_drive_to_examine>'.\n", argv[0] );
    exit( 1 );
  }

  drive = toupper( argv[1][0] );
  if( drive < 'A' || 'Z' < drive )
  {
    printf( "Run like this: '%s <letter_of_drive_to_examine>'.\n", argv[0] );
    exit( 1 );
  }

  sprintf( tmp_path, "%c:/", drive );
  _put_path( tmp_path );
  regs.x.ax = 0x7303;
  regs.x.ds = regs.x.es = __tb_segment;
  regs.x.dx = regs.x.di = __tb_offset;
  regs.x.cx = 0x100; /* Buffer length. Actually ~70 bytes would be enough */
  __dpmi_int (0x21, &regs);

  if (regs.x.flags & 1)
  {
    ret = -1;
  }
  else
  {
    ret = regs.x.ax;
  }
  free   = _farpeekl (_dos_ds, __tb + 0x0c);
  bsize  = _farpeekl (_dos_ds, __tb + 0x08)
    * _farpeekl (_dos_ds, __tb + 0x04);
  blocks = _farpeekl (_dos_ds, __tb + 0x10);

  printf( "AX0x7303.org on %c: -> 0x%x, (%d), bsize = %ld, blocks = %ld, bfree = %ld.\n", drive, ret, errno, bsize, blocks, free);
  printf( "bsize*blocks = %lld = %ld*%ld = %lld * 1024.\n", bsize*(long long)blocks, bsize, blocks, bsize*(long long)blocks/1024 );
  printf( "\n" );

#define OFFS (270)
  sprintf( tmp_path, "%c:/", drive );
  _put_path( tmp_path );
  _farsetsel( _dos_ds );
  for( i = 0; i < 0x100; i++ )
  {
    _farnspokeb( OFFS + i, 0 );
  }
  regs.x.ax = 0x7303;
  regs.x.ds = regs.x.es = __tb_segment;
  regs.x.dx = __tb_offset;
  regs.x.di = __tb_offset + OFFS;
  regs.x.cx = 0x100; /* Buffer length. Actually ~70 bytes would be enough */
  __dpmi_int (0x21, &regs);

  if (regs.x.flags & 1)
  {
    ret = -1;
  }
  else
  {
    ret = regs.x.ax;
  }
  free   = _farpeekl (_dos_ds, __tb + OFFS + 0x0c);
  bsize  = _farpeekl (_dos_ds, __tb + OFFS + 0x08)
    * _farpeekl (_dos_ds, __tb + OFFS + 0x04);
  blocks = _farpeekl (_dos_ds, __tb + OFFS + 0x10);

  printf( "AX0x7303.zero on %c: -> 0x%x, (%d), bsize = %ld, blocks = %ld, bfree= %ld.\n", drive, ret, errno, bsize, blocks, free);
  printf( "bsize*blocks = %lld = %ld*%ld = %lld * 1024.\n", bsize*(long long)blocks, bsize, blocks, bsize*(long long)blocks/1024 );
  printf( "\n" );


  /* Get free space info from Extended Drive Parameter Block. */
  regs.x.ax = 0x7302;
  regs.h.dl = drive - 'A'+1;
  regs.x.es = __tb_segment;
  regs.x.di = __tb_offset;
  regs.x.cx = 0x100; /* 256 bytes should be enough (RBIL says
                        0x3f). */
  __dpmi_int(0x21, &regs);
  if (regs.x.flags & 1)
  {
    ret = -1;
  }
  else
  {
    ret = regs.x.ax;
  }
  printf( "AX0x7302 on %c: -> 0x%x, (%d), bsize = %ld, blocks = %ld, bfree = %ld.\n", drive, ret, errno, bsize, blocks, free);
  printf( "bsize*blocks = %lld = %ld*%ld = %lld * 1024.\n", bsize*(long long)blocks, bsize, blocks, bsize*(long long)blocks/1024 );
  printf( "\n" );

  ret = - ! use_AX0x1510(drive - 'A', &blocks, &free, &bsize);
  printf( "AX0x1510 on %c: -> 0x%x, (%d), bsize = %ld, blocks = %ld, bfree = %ld.\n", drive, ret, errno, bsize, blocks, free);
  printf( "bsize*blocks = %lld = %ld*%ld = %lld * 1024.\n", bsize*(long long)blocks, bsize, blocks, bsize*(long long)blocks/1024 );
  printf( "\n" );

  ret = use_AH0x36(drive - 'A', &blocks, &free, &bsize);
  printf( "AH0x36 on %c: -> 0x%x, (%d), bsize = %ld, blocks = %ld, bfree = %ld.\n", drive, ret, errno, bsize, blocks, free);
  printf( "bsize*blocks = %lld = %ld*%ld = %lld * 1024.\n", bsize*(long long)blocks, bsize, blocks, bsize*(long long)blocks/1024 );
  printf( "\n" );


  return(0);
}
----- Program ends. -----

- Raw text -


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