From: Martin Str|mberg 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 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit 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 #include #include #include #include #include #include #include #include #include #include #include #include /* 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, ®s); 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, ®s); 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, ®s); 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, ®s); /* 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 '.\n", argv[0] ); exit( 1 ); } drive = toupper( argv[1][0] ); if( drive < 'A' || 'Z' < drive ) { printf( "Run like this: '%s '.\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, ®s); 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, ®s); 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, ®s); 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. -----