rico@oscvax.UUCP (03/20/87)
Watch out for this:
char a[65537];
int i;
main()
{
for (i=0;i<65537;i++) a[i] = i;
}
This won't work no matter what memory model you used because the external
storage is too big. Here's the assembler it generates (Manx 3.4, using +p):
;:ts=8
far code
far data
global _a,1 <--- this should be global _a,65537 !!!
global _i,4
public _main
_main:
link a5,#.2
movem.l .3,-(sp)
clr.l _i
.6
move.l _i,d0
lea _a,a0
move.b _i+3,(a0,d0.l) <--- correctly uses long offset due to large
.4 memory model
add.l #1,_i
cmp.l #65537,_i
blt .6
.5
.7
movem.l (sp)+,.3
unlk a5
rts
.2 equ 0
.3 reg d2/d3
public .begin
dseg
end
This isn't too big of a disaster but I wish it would complain rather than
just silently creating bad code...
PS. I love the new 3.4 system, especially db and z. Thank's Jim!
-Rico
--
[NSA food: terrorist, cryptography, DES, drugs, CIA, secret, decode]
[CSIS food: supermailbox, tuna, fiberglass coffins, Mirabel, microfiche]
[Cat food: Nine Lives, Cat Chow, Meow Mix, Crave]
rokicki@rocky.UUCP (03/22/87)
In article <477@oscvax.UUCP>, rico@oscvax.UUCP writes: > Watch out for this: > > char a[65537]; > int i; > > main() > { > for (i=0;i<65537;i++) a[i] = i; > } Also be careful of constructions like: char *a ; unsigned int i ; test() { a[i] ; } If i > 32767, you get the wrong value. Coercing it to a long: a[(long)i] ; doesn't work, either; the compiler throws away the coercion. The only way I've been able to get it to work is as follows: char *a ; unsigned int i ; long zero = 0 ; test() { a[i+zero] ; } -tom
rico@oscvax.UUCP (03/24/87)
Here's a little more elaboration on the problem that Tom Rockiki(sp?) pointed
out. This only causes difficulty when using 16 bit integers as there is no
difference between signed and unsigned addition/indexing when you use the full
width of your registers.
The following two expressions must generate slightly different code, I'm not
sure which one makes the wrong code because I can't remember whether indexing
is signed or unsigned on the 68000. I think it's signed, which would mean
that the a[i] code is wrong...
Lattice probably isn't vulnerable to this bug because it uses only 32 bit int's
Here's the source:
char *a ;
unsigned int i ;
int j;
test() {
a[i] = 1;
a[j] = 2;
}
Aztec C 3.40a generates the following assembler:
;:ts=8
;char *a ;
global _a,4
;unsigned int i ;
global _i,2
;int j;
global _j,2
;
;test() {
public _test
_test:
link a5,#.2
movem.l .3,-(sp)
; a[i] = 1;
move.w _i,d0
move.l _a,a0
move.b #1,(a0,d0.w) <--- wrongo!
; a[j] = 2;
move.w _j,d0
move.l _a,a0 <--- I would've been real impressed if this
move.b #2,(a0,d0.w) wasn't here... oh well maybe next time :-)
;}
.4
movem.l (sp)+,.3
unlk a5
rts
.2 equ 0
.3 reg
public .begin
dseg
end
The code that a[i] = 1 should generate is
move.l #0,d0 ;this gets squeezed into a moveq automagically
move.w _j,d0
move.l _a,a0
move.b #1,(a0,d0.l)
Like I said... this is not a problem if you're using 32 bit integers...
-Rico
P.S.
Nobody's got back to me about my big monitor/tim king questions.
What'sa matter don'tcha got no opinions no more :-)
--
[NSA food: terrorist, cryptography, DES, drugs, CIA, secret, decode]
[CSIS food: supermailbox, tuna, fiberglass coffins, Mirabel, microfiche]
[Cat food: Nine Lives, Cat Chow, Meow Mix, Crave]