Assembly wierdness with integer vars - SOLVED

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Assembly wierdness with integer vars - SOLVED

Post by emiliom »

Ok, so I've got stuff going on that I just don't understand at all and was hoping that someone could clear it up.

Why do single character persistent integer variables cause strange behaviour?
I have a couple of blocks of assembly code stored in 2 different locations as determined by the statements:

DIM M% 512
DIM I% 512

Previously I had called these 'MC%' and 'alienCode%', but I'm just about out of memory and have been thinking about how to break the program up and thought that I might need the variables to persist between programs. Anyway, that's another story. The point is this assembles and runs with no problems, just as before when I had the longer variable names.

I also have some data stored in some variables where the memory was reserved in the same way:

DIM initData% &1B
DIM charData% &DC
DIM shipData% &07
DIM timer% 5

...and later on I load the data into the various blocks of memory. That all works fine. Until I change 'shipData%' to this:

DIM S% &07

Then I get rubbish appear on the screen by way of 2 nonsense characters in the top left, and the left character changes every time I run the code. I get abnormal behaviour if I change any of them to a single char integer variable, EXCEPT timer%. I did this:

DIM T% 5

...and that worked ok. But any of the others and it doesn't work correctly. I thought at first maybe I was using a reserved variable like A%,X%,Y%,C%, etc., just one I didn't know about. But I tried a whole bunch with the same result. Anyone know why this would be?
Last edited by emiliom on Thu Dec 28, 2023 5:14 pm, edited 1 time in total.
julie_m
Posts: 587
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: Assembly wierdness with integer vars

Post by julie_m »

You're not stomping on &400-&4FF at all, are you?
tom_seddon
Posts: 889
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Assembly wierdness with integer vars

Post by tom_seddon »

Make sure you aren't running off the end of any of the arrays when filling them.

--Tom
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

julie_m wrote: Tue Dec 26, 2023 6:51 pm You're not stomping on &400-&4FF at all, are you?
Not as far as I'm aware, but as I don't know what's happening I can't say anything with certainty. I have a BASIC procedure that runs after the machine code is assembled and the data has been inserted into the relevant memory locations and this prints out (on screen) the values of all my integer variables (ie. the starting address for each block) and they are all 29000+, so nothing is being deliberately set up or written to any location that low. And I check the contents of some of the memory locations that hold the data to make sure they match what I put in there, and they do.

I can't say I'm familiar with what goes on between &400-&4FF, other than what it says in the Advanced Guide about it being part of the main workspace for the current language. But I would imagine if I was messing with the language workspace that would be pretty fatal? I don't think I am though. As far as I can tell.
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

tom_seddon wrote: Tue Dec 26, 2023 7:55 pm Make sure you aren't running off the end of any of the arrays when filling them.

--Tom
That was my first thought, but then why would it only happen when using variables with single char names? I literally give them any name with at least 2 chars and it works perfectly. I can't fathom it.

The rubbish I get on the screen though really does look like either an overrun into another variable, or into the screen memory, but at the moment I'm struggling to see how that can be just by changing the variable name. Pretty confusing.
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

I had a thought when I realised that timer% was the last variable and that one was OK. So I moved initData% to after the timer% declaration, made that one the last variable and changed its name to B%. But it didn't work. I just got a load of continuous rubbish on screen as before.
tom_seddon
Posts: 889
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Assembly wierdness with integer vars

Post by tom_seddon »

emiliom wrote: Tue Dec 26, 2023 9:13 pm
tom_seddon wrote: Tue Dec 26, 2023 7:55 pm Make sure you aren't running off the end of any of the arrays when filling them.
That was my first thought, but then why would it only happen when using variables with single char names? I literally give them any name with at least 2 chars and it works perfectly. I can't fathom it.

The rubbish I get on the screen though really does look like either an overrun into another variable, or into the screen memory, but at the moment I'm struggling to see how that can be just by changing the variable name. Pretty confusing.
My justification for recommending checking this is that "DIM longname% 5" will put some stuff on the BASIC heap (variable name, space for variable value, link to next variable of same first char) that "DIM L% 5" won't (as the space for the value of L%, and its name, are pre-allocated). A buffer overrun that's hidden in the long name case (because it scribbles over the variable name data following it in memory, unnecessary once the code is assembled) could end up having visible symptoms in the bulitin variable case (because it scribbles over the next buffer, which follows quickly on from the previous).

--Tom
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

tom_seddon wrote: Tue Dec 26, 2023 10:41 pm My justification for recommending checking this is that "DIM longname% 5" will put some stuff on the BASIC heap (variable name, space for variable value, link to next variable of same first char) that "DIM L% 5" won't (as the space for the value of L%, and its name, are pre-allocated). A buffer overrun that's hidden in the long name case (because it scribbles over the variable name data following it in memory, unnecessary once the code is assembled) could end up having visible symptoms in the bulitin variable case (because it scribbles over the next buffer, which follows quickly on from the previous).

--Tom
Ah...that's interesting. I didn't know how those pre-allocated variables worked. So I could well have been looking in the wrong place because I've been concentrating on the variable I think is at fault when it could be ahead of it.

Cheers. I'll go take another look.
User avatar
jgharston
Posts: 5321
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Assembly wierdness with integer vars

Post by jgharston »

The recommended method for tracking down weird bugs like this is to progressively strip out everything from your program that doesn't change the bug, until you've got the smallest possible broken program to find what the problem is.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.45
(C) Copyright J.G.Harston 1989,2005-2024
>_
julie_m
Posts: 587
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: Assembly wierdness with integer vars

Post by julie_m »

&400-&47F is where BASIC stores @% to Z%, and &480-&4FF is where it stores the heads of the variable chains.

I think tom_seddon is on the right lines, though. If you create space with something like DIM code% 24 and try to store anything past code%+23, you run the risk of stomping on some variable defined later on.
Coeus
Posts: 3557
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by Coeus »

julie_m wrote: Wed Dec 27, 2023 6:28 am &400-&47F is where BASIC stores @% to Z%, and &480-&4FF is where it stores the heads of the variable chains.
To be clear, in normal use the single letter integer variables (@% to Z% and lower case versions of the same), don't need any extra space because the inetger values are stored on page 4 as per julie's comment above. When you do:

Code: Select all

DIM M% 10
This allocates ten bytes on the BASIC heap, so above the currently running program, and then puts the address of the first byte into M%, i.e. the start address of the block is stored on page 4.

Given what you describe you are doing, you may be interested in this: https://github.com/SteveFosdick/vsave which enables the complete set of BASIC variables to be saved and then loaded in again by another or the same program.
julie_m
Posts: 587
Joined: Wed Jul 24, 2019 9:53 pm
Location: Derby, UK
Contact:

Re: Assembly wierdness with integer vars

Post by julie_m »

Or this: https://github.com/JulieMontoya/BCP_design/blob/master/bcp_beeb_build3/VDUMP25 ;)

My one was intended specifically for use when assembling code in chunks, so assumes everything that isn't a string is an address that will fit into a 16-bit integer (and makes some deliberate omissions). You can *SPOOL the output to a file and *EXEC this back in as a bunch of BASIC commands, meaning the values will sit in variable space without the definitions contributing to program size.
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

Ok, well after 2 days I've finally fixed it and it was indeed related to how single char integers work. I had a generic MC routine called execMC that I called from BASIC, passing the variable names as a single parameter, so that the routine would know where to look for the data. When I passed it a long name variable, &601/&602 held the actual address of the data (well, after adding 4 bytes to the low byte). But when using a single char variable it's effectively a pointer to the data, because the variable is in page 4, but not the data. So of course it was looking in completely the wrong place. It was trying to read FROM page 4 instead of where the page 4 variable address was pointing to.

Thanks all for pointing me in the right direction.
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

Coeus wrote: Thu Dec 28, 2023 12:59 pm Given what you describe you are doing, you may be interested in this: https://github.com/SteveFosdick/vsave which enables the complete set of BASIC variables to be saved and then loaded in again by another or the same program.
Thanks for that. For now, I actually already got everything working with persistent variables and managed to break up the code into 4 separate programs, so I can chain build it but work on each file separately. But that will be useful for the future so that I can hang onto more descriptive variable names.

Cheers. :D
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars

Post by emiliom »

julie_m wrote: Thu Dec 28, 2023 2:07 pm Or this: https://github.com/JulieMontoya/BCP_design/blob/master/bcp_beeb_build3/VDUMP25 ;)

My one was intended specifically for use when assembling code in chunks, so assumes everything that isn't a string is an address that will fit into a 16-bit integer (and makes some deliberate omissions). You can *SPOOL the output to a file and *EXEC this back in as a bunch of BASIC commands, meaning the values will sit in variable space without the definitions contributing to program size.
Cheers. Again, I'll keep this in mind for the future as I think I've solved my variable issues for the time being.
emiliom
Posts: 39
Joined: Mon Dec 04, 2023 6:05 pm
Contact:

Re: Assembly wierdness with integer vars - SOLVED

Post by emiliom »

Again, thanks everyone. That was a real head scratcher for me. #-o But at least I'm learning how some of the internals work. I've been trying to break up my code for the last few days to give myself more memory, and this has worked well to solve my current set of problems.

But I'm sure I'll be back with more questions shortly. :lol:
Post Reply

Return to “programming”