Setting and Reading BASIC Variables

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Setting and Reading BASIC Variables

Post by chysn »

I was looking over the BASIC and KERNAL disassembly this evening, to look at the code that sets BASIC variables. Essentially, I was looking at LET, and how it tracks down variable names and populates variables.

I was considering a feature that sets a BASIC variable if a certain condition occurs within a machine language utility. Ultimately, I decided not to implement this feature, in favor of another strategy, but I thought that you folks might benefit from what I learned.

The scope of my project was somewhat limited in that (1) I was only interested in integer (%) variables, and (2) I was only interested in setting a variable with a single-letter name. I haven't yet delved into float and string variables, although I already have a pretty good understanding of float variable storage and manipulation. Updating these routines to use two-letter variables should be trivial, and to handle other variable types less so.

SetIntVal is essentially a miniature replacement for LET. You provide a variable name, n, and a new value, and the subroutine sets the variable n%. You don't have to worry about whether the variable already exists, as this is part of the variable search code at $DOE7. After invoking SetIntVal, you can do PRINT n% to see the value you've set.

An interesting thing about integer variable storage is that the integer is stored backwards, in high/low format. Also, BASIC will treat your value as a signed integer.

Here are the subroutines:

Code: Select all

; Set BASIC Integer
; Preparations
;   A = Letter variable name
;   X = New value, low
;   Y = New value, high       
SetIntVal:  sta $49             ; Stash A for safekeeping
            txa                 ; Push new value bytes for later
            pha                 ; ,,
            tya                 ; ,,
            pha                 ; ,,
            lda $49             ; A is the variable letter name
            jsr GetVarAddr
            ldy #$00            ; Offset for the high byte
            pla                 ; Get high byte value (formerly Y) from stack
            sta ($49),y         ; Store it in BASIC memory at found address
            iny                 ; Advance to next byte
            pla                 ; Get low byte value (formerly X) from stack
            sta ($49),y         ; Store it in BASIC memory
            rts
            
; Get BASIC Integer
; Preparations
;   A = Letter variable name
; Return
;   X = New value, low
;   Y = New value, high
GetIntVal:  jsr GetVarAddr      ; Get the address of the variable data
            ldy #$01            ; Values are stored in high/low order, so
            lda ($49),y         ;   start at offset 1 to get the low byte
            tax                 ;   and put it in X
            dey                 ; Now move to index 0 to get the high byte
            lda ($49),y         ; ,,
            tay                 ;   and put it in Y
            rts

; Get BASIC Variable Address
; Preparations
;   A = Letter variable name
; Effect
;   Sets $49/$4a with pointer to variable storage address
GetVarAddr: ora #$80            ; Variable names are letter with high bit set
            sta $45             ; First character of variable name
            lda #$80
            sta $46             ; Second character of variable name (empty)
            sta $0e             ; Variable type integer (n%)
            asl
            sta $0d             ; Set to numeric variable
            jsr $d0e7           ; Get address of n% by finding or creating new
            sta $49             ; Set low and high bytes of variable address
            sty $4a             ; ,,
            rts
            
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
srowe
Vic 20 Scientist
Posts: 1340
Joined: Mon Jun 16, 2014 3:19 pm

Re: Setting and Reading BASIC Variables

Post by srowe »

The implementation of DUMP in the Programmer's Aid is a good way of understanding the structure of the various variable formats.

https://eden.mose.org.uk/gitweb/?p=rom- ... HEAD#l1743
wimoos
Vic 20 Afficionado
Posts: 348
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: Setting and Reading BASIC Variables

Post by wimoos »

Setting and reading Basic variables from assembly happens a few times in WimBasic.

1. Setting EC and EL during ON ERROR handling and, similar, settting DR and DQ from DIVMOD.

I thought about implementing these in integer variables but didn't find it worth the hassle. All calculations are done in float anyway, so implicit conversions are done all the time when you use integers. Also, all simple variables take 7 bytes so there is no memory saving advantage there. For arrays there is a memory saving of course. $D0E7 is in use here.

2. DUMP follows the list of variables, pointed to by $2D:$2E, in the order they were defined. The list includes the hooks to DEFined FuNctions.

3. SuperNumbers (float) have an address in memory that is calculated from their (single character) name. This results in VERY fast processing.

4. SWAP is a very powerful statement, uses $D08B. Contents of two float, integer or string variables are swapped. For strings, actually not the strings' contents, but the strings' descriptors.

Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
Post Reply