[comp.sys.amiga] Just another BASIC bug

urjlew@ecsvax.UUCP (Rostyk Lewyckyj) (08/05/87)

 [Wisdom for the line eater. For what x is x*x <> x^2 in AMIGABASIC 1.0]

Several weeks ago I posted the following note describing a suspected
Amiga BASIC problem. Since I did not receive a salvo of fire from
the guns of Commodore, I take this as a tacit admision of another
bug in this version of BASIC. I know that the article made it out
into the network by verifying that it had arrived on the batcomputer
at Cornell.
------------  original article follows  ----------------------
Included below is an Amiga BASIC program whose purpose is supposed to be
to read in a packed record of 8204 integers stored as one record of a
random file, and unpack the record into an array. Why I am trying to do
this is irrelevant just now. What is relevant is that this program keeps
getting visited by the GURU and I don't know why.
  
CLEAR , 1030,1030
CLEAR , 40000&,2048
OPEN "R",1,  "matfile", 16410
FIELD 1,16408 AS a$
LSET a$="abcd"
DIM ps%(8203)
ps%(0)=0
b&=VARPTR(ps%(0))
c&=b&
GET #1,1 
a&=SADD(a$)
FOR i&=a& TO a&+16407 STEP 2
POKEW c&,PEEKW(i&)
c&=c&+2
NEXT i&
END

I would much appreciate an explanation of why its happening.
What am I doing wrong, other than trying to program in that stupid BASIC.:-)

By the way the values in the record are {640,100,2,0,0,0,....}, but that
shouldn't matter.
--
  Reply-To:  Rostyslaw Jarema Lewyckyj
             urjlew@ecsvax.UUCP ,  urjlew@tucc.bitnet
  or post to comp.sys.amiga. Others may also be interested 

prm@usl (Patrick Royce Michaud) (08/18/87)

In article <3645@ecsvax.UUCP> urjlew@ecsvax.UUCP (Rostyk Lewyckyj) writes:
>
>Several weeks ago I posted the following note describing a suspected
>Amiga BASIC problem. Since I did not receive a salvo of fire from
>the guns of Commodore, I take this as a tacit admision of another
>bug in this version of BASIC. 

Actually, the people at Commodore may not be the ones to ask about it,
as AmigaBasic is made by Microsoft :-). At any rate, the bug is not in
AmigaBasic, but in your code (see below):

>------------  original article follows  ----------------------
>Included below is an Amiga BASIC program whose purpose is supposed to be
>to read in a packed record of 8204 integers stored as one record of a
>random file, and unpack the record into an array. Why I am trying to do
>this is irrelevant just now. What is relevant is that this program keeps
>getting visited by the GURU and I don't know why.
>  
>CLEAR , 1030,1030
>CLEAR , 40000&,2048
>OPEN "R",1,  "matfile", 16410
>FIELD 1,16408 AS a$
>LSET a$="abcd"
>DIM ps%(8203)
>ps%(0)=0
>b&=VARPTR(ps%(0))
>c&=b&
>GET #1,1 
>a&=SADD(a$)
>FOR i&=a& TO a&+16407 STEP 2
>POKEW c&,PEEKW(i&)
>c&=c&+2
>NEXT i&
>END
>
>I would much appreciate an explanation of why its happening.

Ok, here's my explanation. The problem statement is the "c&=b&". (really!)
Your second CLEAR statement allocates 40000 bytes of space for AmigaBASIC's
data segment. This is where all of your variables (simple variables, arrays,
etc.) are going to be stored. It turns out that the variables aren't stored
helter-skelter as they are declared, but that they do have some semblence
of order placed upon them. You can think of the data segment as a table,
which grows as new variables are declared within the program. The organization
of this table is such that simple variables come first, followed by the
array variables.
   What is happening with your program is this -- you first DIM the ps%()
array, so AmigaBASIC goes and allocates space (16408+overhead bytes) for
it. Later, your program says "b&=VARPTR(ps%(0))". Since simple variables have
to come _before_ array variables in the data segment, AmigaBASIC moves the
ps%() array in the data segment to make enough room for b&. It then gets
the address of ps%() and puts it in b& -- still no problem. But what is
a problem is your next statement-- "c&=b&". Since c& has not been previously
declared, AmigaBASIC has to find space for it. Again, following the "simple
variable before array" rule, it moves the array AGAIN to make enough room
for c&. But, c& is getting the OLD address of the array, and not the
new one. Thus, when you finally get down to POKEWing into what c& thinks
is the start of the array, you're mucking around in territory that isn't
yours, and trashing up the AmigaBASIC data segment.
   The solution to this problem is easy -- make sure that no other "new"
variable declarations occur between the time the VARPTR is done and the
actual POKEW takes place. If any new variable declarations do occur, then
the VARPTR of the array is gonna change (in this case, c&, a&, and i& all
cause the VARPTR of ps%() to change). One solution is to do "c&=0:a&=0:i&=0"
before you do the "b&=VARPTR(ps%(0))" statement. Thus, these variables
will have already been declared by the time the VARPTR takes place, and
it won't move by the time you do the POKEWs.
   A better solution might be to use one of the following (and avoid VARPTR
altogther):

	a&=SADD(a$)	 	    |	a&=SADD(a$)
	FOR i = 0 to 8203	    |	FOR i = 0 to 8203
	   ps%(i) = PEEKW(a&+i*2)   |	   ps%(i) = cvi(mid$(a$,i*2,2))
 	   NEXT i		    |      NEXT i

These present somewhat cleaner alternatives to PEEKW and POKEW, although
I can certainly find reasons why you might want to use PEEKW and POKEW
instead of the above examples. At any rate, I hope this helps to solve
your problem.


Patrick R. Michaud
USL NASA Project Member
"my opinions are my own"
ut-sally!usl!prm