[comp.sys.ibm.pc] Short test for pointer subtract err.

chasm@killer.DALLAS.TX.US (Charles Marslett) (01/09/89)

Here I am submitting a test program that (I hope ;^) all will agree should
run (the array references are all within the arrays, the arrays are all
accepted by the compiler, and the numbers are all reasonable integers).

I have also included the generated code for the MSC pointer subtract bug
and a subroutine with (my idea of) the correct code to generate.

The one point that might be criticized (once again, I hope :-) is that I
am testing both the small and large model code generators in a single program
by compiling in the small model with explicit "far" array and pointer
declarations for the large model code generation.


This block of code is generated for the differences of two small model and
two large model pointers (see the complete C and asm code at the end of this
message).  If you run the test program you will see the results are not what
most people would expect.  I have noted the simple change to the generated
code to produce the right answers for all models but "huge" (since the
"huge" model allows the segment values to differ as well as the offsets).

;|***    printf("C compiler differences: small[3999] = %d, large[5999] = %d\n",
;|***          p1 - localtbl, p2 - testtbl);
; Line 24
	*** 000038	8b 46 fa 		mov	ax,WORD PTR [bp-6]	;p2
	*** 00003b	b9 00 00 		mov	cx,OFFSET _testtbl
	*** 00003e	2b c1 			sub	ax,cx
	*** 000040	99 			cwd	
                                                ^^^ change to SBB DX,DX and all is OK
	*** 000041	b9 0a 00 		mov	cx,10
	*** 000044	f7 f9 			idiv	cx
	*** 000046	50 			push	ax
	*** 000047	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;p1
	*** 00004a	2d 00 00 		sub	ax,OFFSET DGROUP:_localtbl
	*** 00004d	99 			cwd	
                                                ^^^ change to SBB DX,DX and all is OK
	*** 00004e	f7 f9 			idiv	cx
	*** 000050	50 			push	ax
	*** 000051	b8 00 00 		mov	ax,OFFSET DGROUP:$SG115
	*** 000054	50 			push	ax
	*** 000055	e8 00 00 		call	_printf
	*** 000058	83 c4 06 		add	sp,6

This is the test program the code came from:


struct test {
   int itemno;
   struct test far *link;
   char far *ptr;
   };

struct test far testtbl[6000];	/* Far array, 60000 bytes */
struct test localtbl[4000];	/* Near array, 40000 bytes */

main(argc, argv)
   int argc;
   char *argv[];
   {
   int temp;
   struct test *p1;
   struct test far *p2;

   scare_em(&temp);
   p1 = &localtbl[3999];
   p1 += temp;
   p2 = &testtbl[5999];
   p2 += temp;
   printf("C compiler differences: small[3999] = %d, large[5999] = %d\n",
         p1 - localtbl, p2 - testtbl);
   printf("ptrdif differences: small[3999] = %d, large[5999] = %d\n",
         ptrdif(sizeof(struct test), p1, 0, localtbl),
         ptrdif(sizeof(struct test), p2, testtbl));
   }

scare_em(x)
   int *x;
   {
   *x = 0;
   }


And this is the source for my "ptrdif" routine (substitutes for the
C pointer subtract code):


	.model small
	.code
	public	_ptrdif
;
;  ptrdif(sizeof(x[0]), &x[k], &x[m])  ... returns (int)(k-m)
;	for large and compact models
;  ptrdif(sizeof(x[0]), &x[k], 0, &x[m]) ... returns (int)(k-m)
;	for small and medium models
;
_ptrdif	proc	near
	push	bp
	mov	bp,sp
	mov	ax,6[bp]	; Subtract the offsets
	sub	ax,10[bp]	; -- we assume the segments are the same
	sbb	dx,dx		; Divide by the size of an element
	idiv	word ptr 4[bp]	; Remainder in DX, quotient in AX
	pop	bp
	ret
_ptrdif	endp
	end
===========================================================================
Charles Marslett
STB Systems, Inc.  <== Apply all standard disclaimers
Wordmark Systems   <== No disclaimers required -- that's just me
chasm@killer.dallas.tx.us