Hi!
I have non-standard Q:
I need to create/add value to a BASIC-variable in Assembler.
For example:
I have ML program skips to BASIC program loaded from disk..
there are variables NAME$ and DV.
I need to add to NAME$ string "FILE" and to DV number 9.
Next BASIC line is:
LOAD NAME$, DV
and it loads FILE from device 9
but HOW TO DO IT?
Many many thanks everybody and best wishes in New year...
Miro
First, put the two chars of the variable name into $47 and $48. Use 0 if there is no second char. Note this assumes your variable is normal floating point scalar. If it is a string (like X$) then you need to set high bit of second char ($48). If it is an integer (like X%) then you need to set the high bit of both characters ($47 and $48). Hopefully it is not an array, because then even more setup needs to be done.
Next call the routine, $7b0b, with JSRFAR (because if you don't, it returns to BANK14/BANK1.
This will find, and if neccessary create, the variable in Bank 1. The address of the variable is returned in $49 and $4a.
If the variable is "standard", this will point to the first byte of the 5-byte floating-point number.
If the variable is "integer", it points to the first byte of 2-byte integer. Unlike most machine code, the high byte is first!
If it is a string, the returned address points to the descriptor. The descriptor tells you the length (byte 1) and the actual data location (bytes 2 and 3).
Once you know the location, you can use INDFET and INDSTA to read / write the data.
Good luck!
Quote from: Hydrophilic on January 01, 2011, 12:26 PM
Note this assumes your variable is normal floating point scalar. If it is a string (like X$) then you need to set high bit of second char ($48). If it is an integer (like X%) then you need to set the high bit of both characters ($47 and $48).
This part I understand not correctly - maybe is problem English (I used all dictionaries which I have - real/digital)
Please explatin it me step-by-step...
And, Robert, Wishes all good in New year...
Miro
Here is some code from CC128CTL, which is the BASIC interface program for Clock Calendar 128 (http://www.commodore128.org/index.php?board=72.0). It illustrates how to evaluate for a string variable and assign data to it. A similar technique, with appropriate changes, can be used to evaluate numeric variables.
; BASIC interface definitions...
;
endchr =$0a ;string length index
fac1 =$63 ;floating accumulator #1
fac2 =$6a ;floating accumulator #2
forpnt =$4b ;string length pointer
fretop =$35 ;string pool pointer
frespc =$37 ;temporary string pointer
ierror =$0300 ;BASIC error handler vector
index =$24 ;RAM-1 string pointer
linnum =$16 ;integer workspace
varnam =$47 ;variable name (compressed)
varpnt =$49 ;variable desriptor pointer
valtyp =$0f ;expression type (0=numeric)
vartab =$2f ;start of variable storage (RAM1)
;
;
; BASIC ROM subroutines...
;
chkcom =$795c ;check statement for comma
facint =$af0c ;convert FAC1 to integer
fndvar =$7aaf ;find variable, create if not found
frmevl =$af96 ;evaluate complex numeric expression
getbyt =$87f4 ;evaluate simple numeric expression
streval =$877b ;evaluate string expression
strres =$9299 ;reserve space for string
;
;
; kernel indirect interface locations...
;
a_reg =$06 ;indirect .A value
bank =$02 ;indirect JSR bank
pchi =$03 ;indirect JSR address MSB
pclo =$04 ;indirect JSR address LSB
s_reg =$05 ;indirect .S value
x_reg =$07 ;indirect .X value
y_reg =$08 ;indirect .Y value
;
;
; kernel subroutines...
;
indfet =$ff74 ;indirect fetch
jprint =$c00c ;print to screen
jsrfar =$ff6e ;indirect subroutine call
stash =$02af ;write to any bank
stashptr =$02b9 ;write to any bank ZP pointer
;
;
; memory mapping
;
allbank =0 ;all ROMs bank
basbank =15 ;BASIC ROM bank
ram1bank =%01111111 ;RAM-1 only
strbank =1 ;BASIC string storage bank
;
;================================================================================
;
;CREATE STRING VARIABLE
;
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; STRBUF = null-terminated string
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; .A = used
; .X = used
; .Y = used
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
;
;
; determine string length, must be 0-255...
;
crtstr ldy #0
;
crtstr01 lda strbuf,y ;null-terminated string text
beq crtstr02 ;end found
;
iny
bne crtstr01
;
jmp toolng ;string too long (go to BASIC error handler)
;
crtstr02 sty strlen ;save length
;
;
; evaluate string variable passed via SYS call...
;
jsr chkcom ;check for comma, causes syntax error if comma is missing
ldx #<fndvar
ldy #>fndvar
jsr calljsr ;evaluate next variable
bit valtyp ;check variable type
bpl crtstr07 ;not a string, an error in this case
;
;
; find space in RAM-1 for string text...
;
lda strlen ;string length
ldx #<strres ;BASIC reservation sub
ldy #>strres
jsr calljsr ;reserve space, causes out of memory error if there's insufficient space
sta vardesc ;save variable length
stx vardesc+1 ;save string pool address LSB
sty vardesc+2 ;save string pool address MSB
;
;
; copy string text to storage...
;
lda #fretop
sta stashptr ;where string data will go
ldy #0 ;storage index
;
crtstr03 lda strbuf,y ;get byte from new string
beq crtstr04 ;done
;
jsr staram ;write to string space
iny
bne crtstr03
;
;
; generate variable descriptor in RAM-1...
;
crtstr04 clc
tya ;string length
adc fretop ;string pointer
sta frespc ;indirect descriptor pointer
lda fretop+1
adc #0
sta frespc+1
lda #frespc
sta stashptr ;where descriptor address will go
ldy #s_vardes-2 ;descriptor data size
;
crtstr05 lda varpnt,y ;string descriptor address
jsr staram ;append to string data
dey
bpl crtstr05
;
lda #varpnt
sta stashptr ;where descriptor will go
ldy #s_vardes-1 ;descriptor data size
;
crtstr06 lda vardesc,y ;get descriptor data
jsr staram ;write descriptor
dey
bpl crtstr06
;
rts ;string stored, we're done
;
crtstr07 jmp typemm ;type mismatch error
;
;================================================================================
;
;SET UP & CALL KERNAL JSRFAR FUNCTION
;
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; .A = not used but passed to remote sub
; .X = remote function address LSB
; .Y = remote function address MSB
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; .A = value returned by remote function
; .X = value returned by remote function
; .Y = value returned by remote function
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
;
calljsr sta a_reg ;save if needed
php ;capture status register
lda #basbank ;need BASIC ROM (basbank = $0F)
sta bank ;set bank
stx pclo ;set address LSB
sty pchi ;set address MSB
pla ;get status register
sta s_reg ;set
jsr jsrfar ;call function
lda s_reg ;status register
pha ;save
lda a_reg ;returned .A value
ldx x_reg ;returned .X value
ldy y_reg ;returned .Y value
plp ;condition status register
rts
;
;================================================================================
;
;STORE BYTE INTO RAM-1
;
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; .A = byte to store
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
; .A = entry value
; .X = used
; .Y = entry value
; â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"â€"
;
staram ldx #ram1bank ;memory config
jmp stash ;write to string space
;
This is not a complete programâ€"it'll be obvious from the comments what the missing code does. In particular, functions such as TYPEMM are required to map in all ROMs and jump through the BASIC error vector at $0300 with an appropriate error code. All of the need information to do this can be found in Mapping the Commodore 128.
The general form of passing a string variable into a machine language program of this type is SYS ADDR,,,,,V1$,V2$..., where V1$, V2$, etc., are the variables. Note that five commas are required between the SYS address and V1$. The above code will evaluate a variable for type and then assign string data to it. Please carefully study it before asking a lot of questions, as you can learn more that way.
Quote from: MIRKOSOFT
Quote from: Hydrophilic
Note this assumes your variable is normal floating point scalar. If it is a string (like X$) then you need to set high bit of second char ($48). If it is an integer (like X%) then you need to set the high bit of both characters ($47 and $48).
This part I understand not correctly - maybe is problem English (I used all dictionaries which I have - real/digital)
Please explatin it me step-by-step...
If you have a "normal" variable, like "A", then it is floating-point number. Just store "A" ($41) into $47 and 0 into $48.
If you have a string variable, like "A$", then store "A" ($41) into $47 and 0+$80 = $80 into $48.
2 more examples:
A "normal" variable, like "X1", floating-point number. Just store "X" ($58) into $47 and "1" ($31) into $48.
A "string" variable, like "X1$". Store "X" ($58) into $47, and $31+$80 = $B1 into $48.
Once you have $47 and $48 set to the correct "name", then use JSRFAR to call $7b0b.
Quote from: MIRKOSOFT
And, Robert, Wishes all good in New year...
Thank you, and best wishes to you! It seems like you have a lot more hardware to play with than me, so I'm kind of envious...
Hi!
So, now I understand how to create variable...
but how to add any value:
- integer 8-30
- string max. legth 16...
Can you help me?
btw.
I need many users for many types of HW to test it for ACE128 OS... I have not all, it's impossible, but I was very sad when I got long awaited 1541U-II... it's designed only for C64, in C128 mode it makes only problems and not possibilities to use...
So, I sold it... 1541U-I with Ethernet is really usable for both computers, C128 and C64 and no problems with... only emulated REU is problem...if is not used SCPU...
I'm glad you understand how to creat a variable, but now I am confused... can you ask your 2 questions again in more detail?
So,
for example:
I want to create integer variable with name "D" and then add any value between 8 to 30, how to add to variable D e.g. number 9?
I want to create string variable with name "N$" and add any text which can have maximally 16 characters, so, how I add characters and its length? e.g. "THIS FILE", len = 9
Miro
Use the code I provided to "find" the variable, and then use INDSTA to change its contents. Or you can by-pass the KERNAL and call STASH directly.
To call STASH directly, set up a pointer in zero page and the Y register, just as if you were going to do STA(z),Y. When dealing with BASIC variables, z will likely be $49. Anyway, store "z" into $2b9. Then set X to an MMU configuration value (for example $7f = BANK 1). Finally call STASH at $2AF. It will store .A into memory and return (but the X register will change).
Also, for string variables, Y should be 0 to 2; for normal floating-point numbers, Y should be 0 to 4; for integers, Y should be 0 or 1.
BDD provided code of how to use STASH (bypass KERNAL INDSTA), along with an example of JSRFAR. And how to set a string descriptor. All good stuff to know.
MIrko-
I'd listen to Hydro, cuz he knows what he's talking about.
If your trying to, at first.. find a string, or integer, and in anohter routine, add a buffer , too, a string, i might be able to help.
"Wagner" is the man when it comes to strings... but.. i can send you some source examples.
-Steve
Here is some code that might be helpful to anyone wanting to access variables on the 128. Please note. I did not write 99% of this code. I just arranged it so it would be easy to find. I hope this is not out of line.
This code has 2 routines. 1st routine will create a string variable (I$) from whatever is stored in DATA (at end of source)
2nd routine will read the contents of I$ and print it to the screen.
Feel free to comment or make any changes to make this better. I hope this helps anyone who is looking for this type of information.
; COMMODORE 128 STRING ROUTINES
; I DID NOT WRITE MOST OF THIS CODE. JUST COMBINED IT TO MAKE IT WORK
; THANKS TO THOSE WHO DID MOST OF THE HARD WORK
; STARTLOC + 0 WILL COPY THE CONTENTS OF DATA INTO I$
; DATA IS DEFINED AT THE END OF THIS SOURCE AND IS A NULL TERMINATED STRING
; STARTLOC + 3 WILL FIND THE STRING I$ AND PRINT ITS CONTENTS TO THE SCREEN
; THIS CODE CAN BE EASILY MODIFIED TO CHANGE WHICH VARIABLE IS IS LOOKING FOR.
; SOURCE IS IN 64TASS FORMAT - SHOULD BE EASY TO MODIFY TO YOUR FAVORITE ASSEMBLER
FRETOP = $35
FRESPC = $37
VARNAM = $47
VARPNT = $49
STRPNT = $52
LENGTH = $63
JSRFAR = $2CD
NEWFAR = $2A2-22
PTRGET = $7B0B
STRLIT = $869A
INDFET = $FF74 ;KERNAL JUMPS
INDSTA = $FF77
*= $1300
JMP J1 ; WRITE CONTENTS OF DATA TO STRING
JMP J2 ; FIND STRING, AND PRINT ITS CONTENTS
J1 LDA #"i"
LDY #$80 ; I$
JSR STRFIN ; SETUP VARIABLE NAME
JMP STRSTR ; STORE CONTENTS OF "DATA"
J2 LDA #"i"
LDY #$80 ; I$
JSR STRFIN
JSR STRGET
LDA #STRPNT+1 ; ZP STARTING ADDRESS OF STRING (LO BYTE)
STA FETCH+1 ; UPDATE OUR FETCH ROUTINE TO FIND IT
LDA STRPNT ; STRING LENGTH
BNE + ; CONTINUE PRINTING IF ITS NOT 0 LENGTH
RTS ; IF ITS NULL, EXIT OUT
+ LDY #0 ; PRINTS CONTENTS OF THE STRING TO THE SCREEN
- STY TEMPY ; SAVE Y
jsr FETCH ; GET BYTE FROM STRING
JSR $FFD2 ; PRINT IT
LDY TEMPY ; RESTORE Y
INY
CPY STRPNT ; LENGTH OF STRING
BCC - ; LOOP UNTIL END OF STRING
RTS
TEMPY .BYTE 0
STRGET LDY #2
- LDX #1
LDA #VARPNT
JSR INDFET
STA STRPNT,Y
DEY
BPL -
RTS
STRFIN PHA
TYA
PHA
JSR DUPFAR ; DUP AND MOD JSRFAR
PLA
TAY ; Y WILL CONTAIN #$80 IF JUST SINGLE CHAR VARIABLE (A$, ETC)
PLA
STA VARNAM
STY VARNAM+1
LDA #$FF ; FLAG FOR TYPE $
STA $0F
LDA #14 ; BANK 14
STA $02
LDA #>PTRGET
STA $03
LDA #<PTRGET
STA $04
JMP NEWFAR ; CALL PTRGET AT $7B0B
STRSTR LDA #14
STA $02
LDA #>STRLIT
STA $03
LDA #<STRLIT
STA $04
LDA #<DATA ;ADDRESS OF OUR $
STA $06 ;TO BE ALLOTTED/COPIED
LDA #>DATA
STA $08
JSR NEWFAR ;CALL STRLIT AT $869A
DEC $18 ;CALLING FROM ÃÃŒ,
DEC $18 ;SO UNDO $,
DEC $18 ;DESCRIPTOR STACK
LDA #VARPNT ;ADDRESS OF VARPNT
STA $02B9
LDX #1 ;MMU BANK 1 RAM
LDY #0
LDA LENGTH ;$ LENGTH
JSR INDSTA
LDX #1
INY
LDA FRETOP ;MAKE OUR VARIABLE
JSR INDSTA ;POINT TO COPIED $
LDX #1
INY
LDA FRETOP+1
JSR INDSTA
LDA #FRESPC ;FREESPC ADDRESS WHICH
STA $02B9 ;POINTS TO COPIED $
LDX #1
LDY #0
LDA VARPNT ;MAKE $ POINT BACK TO
JSR INDSTA ;OUR VARIABLE (FOR
LDX #1 ;GARBAGE COLLECTION
INY ;PURPOSES)
LDA VARPNT+1
JMP INDSTA
FETCH LDA #$FF ; ZP pointer to use THIS GETS MODIFYED ** IMPORTANT **
LDX #1 ; bank index 1
JMP $FF74 ; kernal
DUPFAR LDY #21
- LDA JSRFAR,Y
STA NEWFAR,Y
DEY
BPL -
LDA $FF00 ; MODIFY TO RETURN TO
STA NEWFAR+17 ; CALLING BANK
RTS
DATA .BYTE "hello world!",0
Here is an issue I am having. Hope someone can help.
I modified BBD's code and just kept the parts to create a string.
I can BANK15:SYS DEC("1300"),,,,,A$
It returns "Hello World" in a$ just like it should.
Here is my problem: Eventually I get an out of memory error.
Simple program
10 BANK15
20 SYS DEC("1300"),,,,,A$:PRINT A$: A$="HI":PRINT A$:GOTO20
As you can imagine, this prints "HELLO WORLD" and next line "HI" over and over again. This will run for about 10-15 minutes and then will give me an out of memory error. If I view bank 1 it seems to be filled up with HI (and I think HELLO WORLD, not at my main computer right now). Seems that its not doing garbage collection?
I can post the ML code if needed, but seems kind of redundant since its 99% unmodifyed BBD code posted above.
Any help is appreciated.
Thanks for sharing! From looking at the code, it seems the problem is in your STRSTR. It seems you set the correct data address in the string descriptor, but the wrong address in the "back pointer" used during garbage collection.
You could try replacing your code
LDA #FRESPC ;FREESPC ADDRESS WHICH
STA $02B9 ;POINTS TO COPIED $
LDX #1
LDY #0
LDA VARPNT ;MAKE $ POINT BACK TO
JSR INDSTA ;OUR VARIABLE (FOR
LDX #1 ;GARBAGE COLLECTION
INY ;PURPOSES)
LDA VARPNT+1
JMP INDSTA
with this code
LDA #FRETOP ;POINTER TO NEW STRING DATA
STA $02B9 ;POINTER FOR INDSTA
LDX #1
LDY LENGTH ;AFTER STRING DATA
LDA VARPNT ;MAKE "BACK-POINTER" LOW
JSR INDSTA ;FOR GARBAGE COLLECTION
LDX #1
INY
LDA VARPNT+1 ;MAKE "BACK-POINTER" HIGH
JMP INDSTA
Just an idea... I haven't actually tested it because I don't have a compiler on this PC. Good luck!
Thanks for the reply. I will give it a shot when I get home and let you know how it goes.
I changed the code and I get the same thing. It will run for about 5-10 minutes and then get an out of memory error.
Granted, this is running on Vice. I did not try it on real hardware to be 100% sure but vice is usually pretty good.
Silly me, I didn't realize the far call to STRLIT setup the FRESPC pointer to the end of the string... so both versions do exactly the same thing!
This got me curious as to the problem so, although I don't have a compiler here, I have my trusty MONITOR. I typed in most of the code (without the JSRFAR copy) and tried it out. The problem is the old string is not being flagged as garbage when it gets set to a new string. Thus garbage collection will not release it, and you get OUT OF MEMORY.
The solution is to update the "back pointer" of the old string with "delete me" code. This is simply the length of the old string (in the back pointer low byte) and a special $FF (in the back pointer high byte).
So this should work; replace
STRFIN
...
LDA #>PTRGET
STA $03
LDA #<PTRGET
STA $04
JMP NEWFAR ; CALL PTRGET AT $7B0B
with this
LDA #>PTRGET
STA $03
LDA #<PTRGET
STA $04
JSR NEWFAR ; CALL PTRGET AT $7B0B
STREX1 = $87CA ;SET INDEX1,A WITH DESCRIPTOR
LDA #14
STA 2
LDA #>STREX1
STA 3
LDA #<STREX1
STA 4
INDEX1 = $24 ;HEAVLY USED BASIC POINTER
LDX VARPNT
LDY VARPNT+1
STX INDEX1
STY INDEX1+1
JSR NEWFAR ;CALL STREX1
LDA #INDEX1 ;POINTER
STA $2B9 ;FOR INDSTA
LDA 6 ;REGISTER .A FROM STREX1 CALL
BEQ EMPTY ;ZERO LENGTH, NO DATA
TAY ;AFTER DATA, "BACK POINTER" LOW BYTE
LDX #1
JSR INDSTA ;SET LENGTH OF GARBAGE
INY ;INDEX "BACK POINTER" HIGH BYTE
LDA #$FF ;FLAG AS GARBAGE
LDX #1
JMP INDSTA ;SET FLAG
EMPTY
RTS
I can't gaurantee that will compile because I tested it in MONITOR. I've attached the binary I used (string.bin) and a simple BASIC test program (string.bas) which is simply
10 BANK15:DO:PRINT PEEK(55)+256*PEEK(56):SYS4864:LOOP
You can watch as the freespace pointer shrinks down to around 1040 and then garbage collection gets called and it starts over again around 65000. This string manipulation stuff is a lot trickier on the C128, but it has a huge benefit. The garbage collection removes about 63K of junk in less than 2 seconds. Of course in a real application it might take an extra second or two.
Ok, I have done some playing and I will try and explain what I found out. I made the changes to the code above and assembled. Ran this program:
10 BANK15:FAST
20 SYS4864:PRINTI$:I$="JEFF BROWN":PRINTI$:GOTO20
After 10 minutes or so, I get an out of memory error.
So I am thinking it must be garbage collection. I changed the code to the following:
10 BANK15:FAST
20 SYS4864:PRINT I$:I$="JEFF BROWN": PRINT I$:X=FRE(1):Y=FRE(0):PRINT X,Y:GOTO20
This should force garbage collection (It does on a C64, not 100% sure on the 128)
If you run this, you will see that when it prints X it is constantly going down. Soon as it gets to about 0 out of memory error.
1 more change to the code:
10 BANK15:FAST
20 I$="":SYS4864:PRINT I$:I$="JEFF BROWN": PRINT I$:X=FRE(1):Y=FRE(0):PRINT X,Y:GOTO20
Now when you run it, you will see that printing x,y does not change. Its been running for about 20 minutes and still going, which I am guessing it would run forever like that.
So is this a garbage collection issue? Is the string not being created properly? I am wondering if we somehow create a null string first and then create the string using the ML would the be the same as doing the I$="" and the SYS to create I$ with data stored in the ML?
I'd love to hear your thoughts. I have learned a lot this last week or so but I still have a LONG way to go, but its fun. :)
Hydro!
You posted at the exact same time. Well it appears I was on the right track. (I think)
Its getting late here, but I can't wait to try your code. Looks like I will have something to play with at lunch time.
I appreciate all of your effort and help.
I'd like to make website or something with just 128 code snippets and share things that may be helpful to newbies like myself. I dont think there is one dediated to 128 code anyway. I have some code that might be useful for other people. I have code to save/restore variables, arrays, etc. basically its a re-dim program. It was used in C64 BBS's and I think I have it working on the 128. Need some more testing. I also have a nice working Swiftlink library (Not the one from Craig Bruce)
Just in case anyone was interested in that sort of stuff.
-Jeff
Glad those error reports were before reading the new post.
You're welcome for the help. Hopefully it will help others too and inspire some nifty new software. It also helps me because I can look up code with the search function (thanks Lance!)
I guess you could start a dedicated site, but I'd just post here for Assembly stuff, in the BASIC (http://www.commodore128.org/index.php?board=65.0)section for heavy BASIC code, or in Tips n Tricks (http://www.commodore128.org/index.php?board=19.0) for those short snippets that might be useful. Being a forum, not simply a static site, makes the software open to discussion and hopefully improvement. That's my take, but I guess if you really love making websites, you could give it a go.
Your code seems to work just fine. Like in your demonstration, it counts down, runs garbage collection and starts all over. GREAT JOB!
I ran it through 1 loop anyway. Might just turn it on and let it run for awhile. I see no reason it shouldn't keep on running. Maybe I will throw some other variables in there from basic to make it really have lots of garbage to collect.
I have no idea how in the world you figured that out but you are my hero. :)
I will try and clean up my code, make it look pretty, and post the complete working code on here later for any one else who might need it.
Here is the working source to create / read a variable in Assembly.
Thanks to Hydro for making this work! This will now flag the variables so garbage collection will remove them and no more out of memory error.
; COMMODORE 128 STRING ROUTINES
; I DID NOT WRITE MOST OF THIS CODE. JUST COMBINED IT TO MAKE IT WORK
; THANKS TO THOSE WHO DID MOST OF THE HARD WORK
; STARTLOC + 0 WILL COPY THE CONTENTS OF DATA INTO I$
; DATA IS DEFINED AT THE END OF THIS SOURCE AND IS A NULL TERMINATED STRING
; STARTLOC + 3 WILL FIND THE STRING I$ AND PRINT ITS CONTENTS TO THE SCREEN
; THIS CODE CAN BE EASILY MODIFIED TO CHANGE WHICH VARIABLE IS IS LOOKING FOR.
; SOURCE IS IN 64TASS FORMAT - SHOULD BE EASY TO MODIFY TO YOUR FAVORITE ASSEMBLER
INDEX1 = $24 ;HEAVLY USED BASIC POINTER
FRETOP = $35
FRESPC = $37
VARNAM = $47
VARPNT = $49
STRPNT = $52
LENGTH = $63
JSRFAR = $2CD
NEWFAR = $2A2-22
PTRGET = $7B0B
STRLIT = $869A
STREX1 = $87CA
INDFET = $FF74 ;KERNAL JUMPS
INDSTA = $FF77
*= $1300
JMP J1 ; WRITE CONTENTS OF DATA TO STRING
JMP J2 ; FIND STRING, AND PRINT ITS CONTENTS
J1 JSR DUPFAR
LDA #"i"
LDY #$80 ; I$
JSR STRFIN ; SETUP VARIABLE NAME
JMP STRSTR ; STORE CONTENTS OF "DATA"
J2 LDA #"i"
LDY #$80 ; I$
JSR STRFIN
JSR STRGET
LDA #STRPNT+1 ; ZP STARTING ADDRESS OF STRING (LO BYTE)
STA FETCH+1 ; UPDATE OUR FETCH ROUTINE TO FIND IT
LDA STRPNT ; STRING LENGTH
BNE + ; CONTINUE PRINTING IF ITS NOT 0 LENGTH
RTS ; IF ITS NULL, EXIT OUT
+ LDY #0 ; PRINTS CONTENTS OF THE STRING TO THE SCREEN
- STY TEMPY ; SAVE Y
jsr FETCH ; GET BYTE FROM STRING
JSR $FFD2 ; PRINT IT
LDY TEMPY ; RESTORE Y
INY
CPY STRPNT ; LENGTH OF STRING
BCC - ; LOOP UNTIL END OF STRING
RTS
TEMPY .BYTE 0
STRGET LDY #2
- LDX #1
LDA #VARPNT
JSR INDFET
STA STRPNT,Y
DEY
BPL -
RTS
STRFIN STA VARNAM
STY VARNAM+1
LDA #$FF ; FLAG FOR TYPE $
STA $0F
LDA #14 ; BANK 14
LDX #>PTRGET
LDY #<PTRGET
JSR CALLJSR ; CALL PTRGET AT $7B0B
;SET INDEX1,A WITH DESCRIPTOR
LDX VARPNT
LDY VARPNT+1
STX INDEX1
STY INDEX1+1
LDA #14
LDX #>STREX1
LDY #<STREX1
JSR CALLJSR ;NEWFAR ;CALL STREX1
LDA #INDEX1 ;POINTER
STA $2B9 ;FOR INDSTA
LDA 6 ;REGISTER .A FROM STREX1 CALL
BEQ EMPTY ;ZERO LENGTH, NO DATA
TAY ;AFTER DATA, "BACK POINTER" LOW BYTE
LDX #1
JSR INDSTA ;SET LENGTH OF GARBAGE
INY ;INDEX "BACK POINTER" HIGH BYTE
LDA #$FF ;FLAG AS GARBAGE
LDX #1
JMP INDSTA ;SET FLAG
EMPTY RTS
STRSTR LDA #<DATA
STA $06
LDA #>DATA
STA $08
LDA #14
LDX #>STRLIT
LDY #<STRLIT
JSR CALLJSR
DEC $18 ;CALLING FROM ÃÃŒ,
DEC $18 ;SO UNDO $,
DEC $18 ;DESCRIPTOR STACK
LDA #VARPNT ;ADDRESS OF VARPNT
STA $02B9
LDX #1 ;MMU BANK 1 RAM
LDY #0
LDA LENGTH ;$ LENGTH
JSR INDSTA
LDX #1
INY
LDA FRETOP ;MAKE OUR VARIABLE
JSR INDSTA ;POINT TO COPIED $
LDX #1
INY
LDA FRETOP+1
JSR INDSTA
LDA #FRETOP ;POINTER TO NEW STRING DATA
STA $02B9 ;POINTER FOR INDSTA
LDX #1
LDY LENGTH ;AFTER STRING DATA
LDA VARPNT ;MAKE "BACK-POINTER" LOW
JSR INDSTA ;FOR GARBAGE COLLECTION
LDX #1
INY
LDA VARPNT+1 ;MAKE "BACK-POINTER" HIGH
JMP INDSTA
FETCH LDA #$FF ; ZP pointer to use THIS GETS MODIFYED ** IMPORTANT **
LDX #1 ; bank index 1
JMP $FF74 ; kernal
CALLJSR STA $02
STX $03
STY $04
JMP NEWFAR
DUPFAR LDY #21
- LDA JSRFAR,Y
STA NEWFAR,Y
DEY
BPL -
LDA $FF00 ; MODIFY TO RETURN TO
STA NEWFAR+17 ; CALLING BANK
RTS
DATA .BYTE "hello world!",0
Quote from: Racer on January 30, 2011, 11:38 PMHere is the working source to create / read a variable in Assembly.
Nothing like reinventing the wheel! ;D
BDD, tried using your code as an example, but it does not mark for garbage collection and will run out of memory eventually. The code I posted is the only one I found that does unless you have something else or I missed something which is highly possible.