How to create BASIC variable in assembler?

Started by MIRKOSOFT, January 01, 2011, 10:42 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

Hydrophilic

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!
I'm kupo for kupo nuts!

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

BigDumbDinosaur

Here is some code from CC128CTL, which is the BASIC interface program for Clock Calendar 128.  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.
x86?  We ain't got no x86.  We don't need no stinking x86!

Hydrophilic

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...

I'm kupo for kupo nuts!

MIRKOSOFT

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...
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

Hydrophilic

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?
I'm kupo for kupo nuts!

MIRKOSOFT

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
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

Hydrophilic

#8
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.
I'm kupo for kupo nuts!

stiggity

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

Racer

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


Racer

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.

Hydrophilic

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!
I'm kupo for kupo nuts!

Racer

Thanks for the reply.  I will give it a shot when I get home and let you know how it goes.

Racer

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.

Hydrophilic

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.
I'm kupo for kupo nuts!

Racer

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.  :)


Racer

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

Hydrophilic

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 section for heavy BASIC code, or in Tips n Tricks 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.
I'm kupo for kupo nuts!

Racer

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.

Racer

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



BigDumbDinosaur

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
x86?  We ain't got no x86.  We don't need no stinking x86!

Racer

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.