USER ERROR: sty variable,x where variable is ZP

discuss pc<>acorn file transfer issues and the use of other utils
Post Reply
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

USER ERROR: sty variable,x where variable is ZP

Post by tricky »

I was working on a converter from 6502Bench to beebasm and seem to have found a bug.
Firstly, I know I should be writing a converter for 6502Bench, but C# makes my skin crawl :O
Secondly, this may be know/documented an I just haven't found it.

It looks like if a variable is assigned a value that is < 256, the assembler treats it as 16 bit as far as instruction encoding goes.
AFAIK, there is no way for force an address to be 16bit, which in this case would temporarily be handy as the original code uses 16 bit addressing for some ZP addresses and I am currently adding a NOP after the instruction generated by beebasm to pad it. The reason I am converting to beebasm is to change the code and make some room, so I will be removing the NOPs once it works.

Code: Select all

    trk_axis_hi          = &9D    
    trk_axis_lo          = &B0    
                                  CHECK_ADDR &51FB
}
.ApplyTrackAxis                   ;assume positive
{
    ldy #&00                      ;assume positive
                                  CHECK_ADDR &51FD
    lda trk_axis_lo,X             ;get value
                                  CHECK_ADDR &51FF
    bpl _IsPos                    ;is positive, branch
                                  CHECK_ADDR &5201
    dey                           ;make negative
                                  CHECK_ADDR &5202
._IsPos                           ;sign-extend axis value
    sty trk_axis_hi,X             ;sign-extend axis value
In beebasm, this gives the error:

Code: Select all

MissileCommand.asm:1039: error: X indexed mode does not exist for this instruction.

    sty trk_axis_hi,X             ;sign-extend axis value
There is no version string, but this seems to have come from the "beebasm-proposed-updates" branch.
I haven't tried the head (wherever that is) as it is missing some other bits that I use.

PS I'm an idiot: beebasm 1.09
Last edited by tricky on Fri Mar 04, 2022 5:17 pm, edited 1 time in total.
User avatar
sweh
Posts: 3314
Joined: Sat Mar 10, 2012 12:05 pm
Location: 07410 New Jersey
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by sweh »

Is there something else outside of that code segment? Maybe these are conditional defines?

In my very very simple test it worked

Code: Select all

$ beebasm --help | head -1
beebasm 1.10-pre

$ cat  x
    trk_axis_hi          = &9D    
    trk_axis_lo          = &B0    

    ldy #&00                      ;assume positive
    lda trk_axis_lo,X             ;get value
    bpl _IsPos                    ;is positive, branch
    dey                           ;make negative
._IsPos
    sty trk_axis_hi,X             ;sign-extend axis value

SAVE "y",0,0
$ beebasm -v -i x
     0000   A0 00      LDY #&00
     0002   B5 B0      LDA &B0,X
     0004   10 01      BPL &0007
     0006   88         DEY
._IsPos
     0007   94 9D      STY &9D,X
Saving file 'y'
Processed file 'x' ok
Rgds
Stephen
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by tricky »

It looks like the variable is stored in the symbol table as:

Code: Select all

trk_axis_hi@247_0
but is being looked up as:

Code: Select all

trk_axis_hi@259_0
This looks like for loop scoping (everything is a for loop if it needs a new scope) - I'll dig deeper.
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by tricky »

Sorry sweh, missed your post.
"trk_axis_hi = &9D" is line 1024 and there is an open { at line 986 but no conditional assembly.
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by tricky »

Agh!
Why didn't I see that they were in different scopes!
I thought variables (or whatever they are called) were global!
That is annoying!

The problem with this converter is that 6502Bench supports local labels that are scoped by the nearest global variables which I am converting to { } on global variable that enclose local variables.
I didn't know if there variables were supposed to be local, it looked like they were, but I guess not!
User avatar
sweh
Posts: 3314
Joined: Sat Mar 10, 2012 12:05 pm
Location: 07410 New Jersey
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by sweh »

Are you sure you're not multiply defining this variable?

If you define inside { } then it's local.

So, for example

Code: Select all

{
    trk_axis_hi          = &9D    
    trk_axis_lo          = &B0    
}

    ldy #&00                      ;assume positive
    lda trk_axis_lo,X             ;get value
    bpl _IsPos                    ;is positive, branch
    dey                           ;make negative
._IsPos
    sty trk_axis_hi,X             ;sign-extend axis value

SAVE "y",0,0
$ beebasm -i x
x:7: error: Symbol not defined.

    lda trk_axis_lo,X             ;get value
If we define it as a 16btit outside of that area then I can replicate your issue

Code: Select all

$ head -5 x
trk_axis_hi=&1234

{
    trk_axis_hi          = &9D    
    trk_axis_lo          = &B0    
$ head -6 x
trk_axis_hi=&1234

{
    trk_axis_hi          = &9D    
    trk_axis_lo          = &B0    
}
$ beebasm -i x
x:13: error: X indexed mode does not exist for this instruction.

    sty trk_axis_hi,X             ;sign-extend axis value
Rgds
Stephen
User avatar
sweh
Posts: 3314
Joined: Sat Mar 10, 2012 12:05 pm
Location: 07410 New Jersey
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by sweh »

tricky wrote: Wed Mar 02, 2022 1:16 pm Agh!
Why didn't I see that they were in different scopes!
I thought variables (or whatever they are called) were global!
That is annoying!

The problem with this converter is that 6502Bench supports local labels that are scoped by the nearest global variables which I am converting to { } on global variable that enclose local variables.
I didn't know if there variables were supposed to be local, it looked like they were, but I guess not!
beebasm "variables" aren't really variable; they're constant symbols. Once set they can't be changed.
So, for example

Code: Select all

trk_axis_hi=&1234
trk_axis_hi=100
would result in the error "Symbol already defined."

The { } syntax allows for a local symbol to be defined that masks the original symbol within the scope of the {..} section.
Rgds
Stephen
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by tricky »

It was only defined once.
The reason that it was saying that it couldn't generate the ZP only instruction is that beebasm assumes that an address is 16bit if it doesn't know what it is. It didn't know because I had them in separate scopes!

6502bench clears its labels with "Clear variables", prefixed with a non-ascii char and a space IIRC.
It can also have two local variables with the same name in the same scope, seemingly without any way to distinguish them.
It does know in the tool, so I'm guessing that it renames them when assembling from the tool - my next project!
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by tricky »

Is there a way to make variables global, like .* for labels?
SteveF
Posts: 1663
Joined: Fri Aug 28, 2015 9:34 pm
Contact:

Re: Possible beebasm bug: sty variable,x where variable is ZP

Post by SteveF »

tricky wrote: Wed Mar 02, 2022 1:45 pm Is there a way to make variables global, like .* for labels?
I don't think there is, although I agree it would be a nice feature to have. It would raise questions of syntax though, the following code shows off some (non-exclusive) ideas off the top of my head:

Code: Select all

{
   foo *= 42 ; option 1/n - define foo in global scope
   *foo = 42; option 2/n - define foo in global scope
   foo ^= 42; option 3/n - define foo in parent scope
   ^foo = 42 ; option 4/n - define foo in parent scope
   
   ; option 5/n
   foo = 42 ; define label as local
   global foo ; then promote it to global
   
   ; option 6/n
   foo = 42; define label as local
   parent foo; then promote it to parent scope
}

lda #foo ; should assemble as lda #42
I've usually just accepted that some constants will have to be defined outside a scope, even if it's a bit uglier than necessary.

I have a vague feeling the implementation of any of these isn't completely trivial, otherwise I would probably have done it by now, but it may just be that I was feeling cowardly at the times I felt the desire to have this feature. It's also possible the question of what syntax to use put me off. :-)

Edited: Just as an example of why it would sometimes make code nicer not to have to just define things in the right scope:

Code: Select all

{
   widget_size = 3
   max_widgets = 40
   widget_buffer_size = widget_size * max_widgets
}
; Allocate widget buffer
lda ptr:clc:adc #lo(widget_buffer_size):sta ptr
lda ptr+1:adc #hi(widget_buffer_size):sta ptr+1
This won't build, because widget_buffer_size is confined to a scope. But it can't be moved in isolation to the outer scope, because it needs widget_size and max_widgets. So all three constants have to be moved into the global scope, even though perhaps widget_size and max_widgets don't actually need to be accessed by anything outside the scope and it would be nice not to expose them so no code accidentally depends on them. If widget_buffer_size could be exported to the parent or global scope somehow that would be better.
User avatar
TobyLobster
Posts: 618
Joined: Sat Aug 31, 2019 7:58 am
Contact:

Re: USER ERROR: sty variable,x where variable is ZP

Post by TobyLobster »

I like the human readable 'global' and 'parent' names. Perhaps options 5/n and 6/n could be combined into single lines:

Code: Select all

    global foo = 42       ; option 7/n
    parent bar = 32767    ; option 8/n
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: USER ERROR: sty variable,x where variable is ZP

Post by tricky »

For what I needed, I could declare them both and then delete the couple of duplicate globals.
If the value is 16 bit, I guess you could do something ugly like:

Code: Select all

{
   widget_size = 3
   max_widgets = 40
   widget_buffer_size_P = P%
   P% = widget_size * max_widgets
.*widget_buffer_size
   P% = widget_buffer_size_P
}
I have not tested this!
I was thinking var% like BBC BASIC (@% and A%-Z%), but I don't think that I like it as it is a coincidence that those %vars are global!
global foo = 42 seems like a good solution, not so sure about parent parent ... bar but you don't have to use it!
SteveF
Posts: 1663
Joined: Fri Aug 28, 2015 9:34 pm
Contact:

Re: USER ERROR: sty variable,x where variable is ZP

Post by SteveF »

TobyLobster wrote: Fri Apr 08, 2022 8:03 am I like the human readable 'global' and 'parent' names. Perhaps options 5/n and 6/n could be combined into single lines:

Code: Select all

    global foo = 42       ; option 7/n
    parent bar = 32767    ; option 8/n
I rather like this, perhaps with the option to omit the '=...' part to promote an existing label to another scope as well if I'm really being greedy (i.e. options 5/6 are still available).

However, if someone feels like having a go at implementing this and one syntax happens to be much easier to implement than another due to how the beebasm code happens to work, I'd love to have this feature with any not-totally-insane syntax. :-)
tricky wrote: Fri Apr 08, 2022 11:28 am For what I needed, I could declare them both and then delete the couple of duplicate globals.
If the value is 16 bit, I guess you could do something ugly like:

Code: Select all

{
   widget_size = 3
   max_widgets = 40
   widget_buffer_size_P = P%
   P% = widget_size * max_widgets
.*widget_buffer_size
   P% = widget_buffer_size_P
}
I have not tested this!
This is ingenious! I just tried it and it doesn't work with P% (I am not sure if this is a bug or not):

Code: Select all

$ beebasm -do z.ssd -i trickyP.asm -v
trickyP.asm:10: error: Symbol already defined.

   P% = widget_buffer_size_P
   ^
but if I use "org" instead it does:

Code: Select all

$ cat tricky.asm 
    org &2000
    lda #'a'

{
   widget_size = 3
   max_widgets = 40
   widget_buffer_size_P = P%
   org widget_size * max_widgets
.*widget_buffer_size
   org widget_buffer_size_P
}

    jsr &ffee
    lda #widget_buffer_size
    rts
$ beebasm -do z.ssd -i tricky.asm -v
     2000   A9 61      LDA #&61
.widget_buffer_size
     2002   20 EE FF   JSR &FFEE
     2005   A9 78      LDA #&78
     2007   60         RTS
For a few joyful moments I thought this trick could be wrapped up in a macro, but as soon as I tried it I realised it almost certainly can't be. You could do it by using a preprocessor to tweak your source code before handing it over to beebasm, but that's probably more pain than it's worth.

Edit: I might guess (I haven't checked the code) that it doesn't work with P% because P% isn't treated specially inside a scope. It might be nice to make an exception for this, but at the same time it does have a certain logic to it as it is.
User avatar
tricky
Posts: 7694
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: USER ERROR: sty variable,x where variable is ZP

Post by tricky »

Story, I've never set P%, ORG would be the way to go.

I can't think of a reason that it wouldn't work in a macro as the .* And ORG are global and the rest local.
They are not text substitution macros like C DOH!

The easiest to implement would probably be to make variables starting with an _ global as that wouldn't need special parsing, just an if stars with _ look/set in global scope.
Post Reply

Return to “software & utilities for the pc, mac or unix”