[comp.sys.mac.programmer] string initialization in assembly from Think C

stay@ohs.UUCP (Steve Taylor) (07/18/90)

I'm using Think C 4.01 on an SE 30.  I was getting an address error
(On a Mac Plus) so I checked out the assembled code in macsbug and
here's what I found:

C Code:

CompareP(p1, p2)
char *p1, *p2;
{
	int 		i, ok = true;
	long		secs;
	DateTimeRec	theDate;
	char		backp[4][16] = {
	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
	};

     /* ...Actual function code... */
}

	Compiled by Think C, disassembled by macsbug:

COMPAREP

+0000	LINK	a6, #$FFAA
	MOVEQ	#$01, D0
	MOVE.W	D0, -$004(a6)
	LEA	-$0056(A6), A0
+000E	LEA	-$2D97(A5), A1
	MOVEQ	#$0F, D0
+0014	MOVE.L	(A1)+, (A0)+
	DBF	D0, COMPAREP+0014
	...

Now, since at the time of execution A5 is 0021638E, it's obvious that
the odd address put into A1 on line 000E and accessed (by a long
operation) on line 0014 is the problem.  What I want to know is (1) how
did my my string constants get put at an odd offset from A5),
and (2) if Think C put them there, shouldn't it have known
it couldn't MOVE.L them?  And, (3) how am I supposed to initialize
my array of strings so that this doesn't happen?  (I changed it to
a BlockMove, Thus performing my own initialization, and it worked fine.)
Am I making ridiculous assumptions about what all of this means?

Notes:
	The address error occured on a Mac Plus and SE, but not an SE 30
		or II or IIcx, naturally.
	Go ahead.  Laugh at my initialization technique.
	No, they aren't all the same character sequence.  I got sick
		of typing them.
	Yes, I have "Separate STRS" checked.

Thanks.
-- 
Steven H. Taylor  stay@ohs.uucp  trACE(tm) Development, Alpine School District.
-------------------------------------------------------------------------------
"Ha Ha," said Eeyore bitterly.  "Merriment and whatnot.  Don't apologize.
It's just what WOULD happen."

steve@uswmrg2.UUCP (Steve Martin) (07/18/90)

In article <569@ohs.UUCP> stay@ohs.UUCP (Steve Taylor) writes:
>I'm using Think C 4.01 on an SE 30.  I was getting an address error
>(On a Mac Plus) so I checked out the assembled code in macsbug and
>here's what I found:
>
>C Code:
>
>CompareP(p1, p2)
>char *p1, *p2;
>{
>	int 		i, ok = true;
>	long		secs;
>	DateTimeRec	theDate;
>	char		backp[4][16] = {
>	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
>	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
>	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
>	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
>	};
>}
>
>Now, since at the time of execution A5 is 0021638E, it's obvious that
>the odd address put into A1 on line 000E and accessed (by a long
>operation) on line 0014 is the problem.  What I want to know is (1) how
>did my my string constants get put at an odd offset from A5),
>and (2) if Think C put them there, shouldn't it have known
>it couldn't MOVE.L them?  And, (3) how am I supposed to initialize
>my array of strings so that this doesn't happen?  (I changed it to
>a BlockMove, Thus performing my own initialization, and it worked fine.)
>Am I making ridiculous assumptions about what all of this means?

Yup, I ran into that same problem.  I think it is a bug in Think C.  To
fix it declare your char array to be static.  Think C then word aligns
the data!  Don't ask me why.

-- 
Steve Martin                         | Nothing I say can be held against
U S West Marketing Resources Group   | Me or my employer!
(...uswat.uswest.com!uswmrg2!steve)

jimc@isc-br.ISC-BR.COM (Jim Cathey) (07/20/90)

In article <569@ohs.UUCP> stay@ohs.UUCP (Steve Taylor) writes:
>I'm using Think C 4.01 on an SE 30.  I was getting an address error
>...
>	char		backp[4][16] = {
>	"\x39\x0c\x1d\x1a\x05\x00\x00\x37\x00\x0c\x43\x3b\x0a\x01\x09\x0e",
>...
>	Compiled by Think C, disassembled by macsbug:
>
>COMPAREP
>
>+0000	LINK	a6, #$FFAA
>	MOVEQ	#$01, D0
>	MOVE.W	D0, -$004(a6)
>	LEA	-$0056(A6), A0
>+000E	LEA	-$2D97(A5), A1
>	MOVEQ	#$0F, D0
>+0014	MOVE.L	(A1)+, (A0)+
>	DBF	D0, COMPAREP+0014
>	...
>
>Now, since at the time of execution A5 is 0021638E, it's obvious that
>the odd address put into A1 on line 000E and accessed (by a long
>operation) on line 0014 is the problem.  What I want to know is (1) how
>did my my string constants get put at an odd offset from A5),
>and (2) if Think C put them there, shouldn't it have known
>it couldn't MOVE.L them?  And, (3) how am I supposed to initialize
>my array of strings so that this doesn't happen?  (I changed it to
>a BlockMove, Thus performing my own initialization, and it worked fine.)
>...
>	Yes, I have "Separate STRS" checked.

It appears to be a bug in Think C.  It put the strings to initialize with
in globals space, but not aligned in any particular fashion, and there was
something else in there of odd length (like another quoted string).  I don't
know why they ended up there 'cause you had Separate STRS checked.  When it
went to generate the code to initialize your auto variable, it didn't realize
that the alignment of the source wasn't right.  It should have 1) generated a
call to BlockMove instead, or 2) wasted a byte in globals space to align the
string constant, or 3) used a less speedy byte move loop.

Potentially, of course, aligning the constant strings could waste a lot of
space depending on how many string items you had (and their lengths).

I myself don't ever use initializers on auto variables as a matter of style.
This emphasizes (to me) that these variables are on the stack frame and are
_not_ cleared for me and might contain random junk.  Also, it means that there
is no 'hidden' executable code generated, like the assignment loop that you're
having trouble with.  I've even seen guys hide function calls up in the
variable declaration block!  Talk about hard to notice...

Thus, I favor LSC solving the problem by using method 3 above as a built-in
penalty for a nasty coding style.  1/2 :-)  Most Un*x compilers use method
2.  Method 1 would probably be Think's best choice as BlockMove is a register
based call, and the MOVE+DBRA is actually larger than the trap, albeit faster
to some degree (at least for small strings).

Should these strings actually be in a resource?  You wouldn't have this
problem then, and ResEdit could get at them.  They're just a GetResource
away...

+----------------+
! II      CCCCCC !  Jim Cathey
! II  SSSSCC     !  ISC-Bunker Ramo
! II      CC     !  TAF-C8;  Spokane, WA  99220
! IISSSS  CC     !  UUCP: uunet!isc-br!jimc (jimc@isc-br.iscs.com)
! II      CCCCCC !  (509) 927-5757
+----------------+
			"With excitement like this, who is needing enemas?"