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