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