Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[SOLVED] Array layout bug - regression in 1.18.3
#1
Please take a look at this simple programme:


Code:
dim a(5) as ubyte => {0, 1, 2, 3, 4, 5}
dim b(5) as ubyte
dim i as uinteger

for i = 0 to 5
    poke @b + i, a(i)
next

cls

for i = 0 to 5
    print a(i), b(i)
next

When compiled with zxbasic 1.18.2 this works as expected - both arrays are same. See the attached image:
   
However, with zxbasic 1.18.3, the programme fails miserably and crashes the Spectrum

In both cases compiled with 
Quote: Wrote:--optimize 2  --output-format=tzx --BASIC --autorun --explicit --strict

Now, this is the simple case made to illustrate the bug. The main problem I have is with character arrays -- I have custom font with cyrilic letters designed in ZXBasicStudio, stored as two dimensional array (95, 7) -- when I want to write cyrilic text I poke the system variable 5C36 to the address of the array minus 256 (@array - $100) and when I want to print latin text, I just poke this variable back to default value  $3C00. This worked perfectly until version 1.18.3 came out. Now, everything is broken, as the characters in the array are obviously not stored continuously in memory.
What happend with array layout?




Now I tried to see the address of the array itself, compared with the addresses of array elements:
Code:
dim a(5) as ubyte => {0, 1, 2, 3, 4, 5}
dim i as uinteger
cls
print "@a = "; @a
print "------------"
for i = 0 to 5
  print "@a("; i; ") = "; @a(i)
next

The attached image shows the output with zxbasic 1.18.2 compared with zxbasic 1.18.3:
   

It seems that in zxbasic 1.18.3, there are eight bytes between the address of the array itself (@a) and the first element (@a(0) ). The array elements are stored continuously after all.

So, I can workaround the problem with the custom character set that I mentioned in my previous post using:
Code:
poke (uinteger $5c36, @charset(0,0) - $100) ' the address of the first element
instead of
Code:
poke (uinteger $5c36, @charset - $0100) ' the address of the array

But still, is there a reason for this, or is it just a bug?

Swan, my ZX Spectrum emulator https://github.com/zoran-vucenovic/swan
Reply
#2
Yes, indeed, 1.18.3 fixes a bug with the @array_var when the the var is an array.
@array_var DOES NOT return the address of the 1st element, but the address of the array descriptor (indeed @array_var is forbidden in other BASIC dialects like FreeBasic). The Array Descriptor is a struct with internal data.
To get the address of the 1st element just use @array_var(0, 0, ...). In your case, use @a(0), etc, as you said.
Note: If the array indexes are constant (not variables) this is computed in compile time to a single actual address of the element, and it's immediate.

The bug was that @array_var was returning the address of the 1st element too.
---
Boriel
Reply
#3
(2025-10-25, 05:18 PM)boriel Wrote: Yes, indeed, 1.18.3 fixes a bug with the @array_var when the the var is an array.
@array_var DOES NOT return the address of the 1st element, but the address of the array descriptor (indeed @array_var is forbidden in other BASIC dialects like FreeBasic). The Array Descriptor is a struct with internal data.
To get the address of the 1st element just use @array_var(0, 0, ...). In your case, use @a(0), etc, as you said.
Note: If the array indexes are constant (not variables) this is computed in compile time to a single actual address of the element, and it's immediate.

The bug was that @array_var was returning the address of the 1st element too.

I see. Now I know how it should be used correctly. Thank you!

Swan, my ZX Spectrum emulator https://github.com/zoran-vucenovic/swan
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)