[comp.sys.amiga] Caveat for Manx C

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]