Jump to content
IGNORED

XMLLNK call >2300 not available in Ext. Basic. Any alternatives?


Recommended Posts

I use Extended Basic 3 and its included assembler.

I am teaching myself TMS assembler and has reached a point where I test passing stuff between Extended basic and assembler. Basic numbers are always floats while assembler uses integers for most calculations. There is a call to convert the float from Extended Basic (XMLLNK DATA >1200) to an integer up to >FFFF. But what about the opposite action...

If I understand the E/A manual correctly, the call to XMLLNK with DATA >2300 is not available, if called from Extended Basic with CALL LINK. Is there a 'standard' solution to this problem like some other ROM routine or a piece of code, that all old hands uses?

I suppose I could store the integer in a predetermined address in MC, switch back and use CALL PEEK to get the high and low byte, and put the combined value back in a variable in Extended Basic. But getting it back as a float via the FAC seems to be the proper solution - except that the routine is not there in Extended Basic.

  • Like 1
Link to comment
Share on other sites

Posted (edited)

For CIF (Convert Integer to Floating Point)

Page 261 of the E/A Manual says It is not loaded by the TI Extended BASIC Loader and may not be used in T I Extended BASIC.

But in the TI Extended BASIC Equates on pages 415 to 418 of the E/A Manual shows that CIF EQU >20 (page 416)

So I dunno. I never had occasion to use this.

 

Edited by senior_falcon
Link to comment
Share on other sites

This code taken from my Canadian Mortgage Loan Calculator program on my GitHub repo.

 

Something similar should work for in assembly to call the GPL routine.

 

You just got to be able to return to XB correctly as normally it's not recommended to call GPL routines when coming from a xb call link.

 

I will see if I can find some old code and paste it here that works for passing numbers between xb and assembly.

 

**************************************** BLWP @MATH 
* UNIVERSAL FLOATING POINT MATH        * DATA LEFT/ADDR 
*                                      *      RIGHT/ADDR 
****************************************      TYPE OF MATH 
FADD   EQU  >0600             XML             ANSWER/ADDR 
FSUB   EQU  >0700             XML 
FMUL   EQU  >0800             XML 
FDIV   EQU  >0900             XML 
CFI    EQU  >1200             XML 
FEXP   EQU  >0024             GPL 
FINT   EQU  >0022             GPL 
CNS    EQU  >0014             GPL 

VSPTR  EQU  >836E             Points to FPV VDP stack pointer in CPU RAM 
VDPSTK DATA >0600             A good free area for roll-out FPV calcs 

MATH   DATA FPVWS,MATH0       BLWP entry vectors 
MATH0  MOV  @VDPSTK,@VSPTR    Reset FPV VDP stack pointer 
       MOV  *R14+,R1          move left to argument 
       LI   R0,ARG            * 
       LI   R2,4              * 
MATH1  MOV  *R1+,*R0+         * 
       DEC  R2                * 
       JNE  MATH1             * 
       MOV  *R14+,R1          move right to fac 
       LI   R0,FAC            * 
       LI   R2,4              * 
MATH2  MOV  *R1+,*R0+         * 
       DEC  R2                * 
       JNE  MATH2             * 
       MOV  *R14+,R0          GET TYPE OF OPERATION 
       CB   R0,@ZERO          If MSByte is ZERO then GPL 
       JEQ  MATH5                               else XML 
       MOV  R0,@MATH3         Do a XML math 
       BLWP @XMLLNK           * 
MATH3  DATA 0                 * 
       JMP  MATH6             * 
MATH5  MOV  R0,@MATH7         Do a GPL math 
       MOV  @VSPTR,R0 
       LI   R1,ARG 
       LI   R2,8 
       BLWP @VMBW 
       BLWP @GPLLNK           * 
MATH7  DATA 0                 * 
MATH6  MOV  *R14+,R1          move fac to answer 
       LI   R0,FAC            * 
       LI   R2,4              * 
MATH4  MOV  *R0+,*R1+         * 
       DEC  R2                * 
       JNE  MATH4             * 
       RTWP                   RETURN TO CALLING PROGRAM 

 

  • Like 5
Link to comment
Share on other sites

3 hours ago, jschultzpedersen said:

I use Extended Basic 3 and its included assembler.

I am teaching myself TMS assembler and has reached a point where I test passing stuff between Extended basic and assembler. Basic numbers are always floats while assembler uses integers for most calculations. There is a call to convert the float from Extended Basic (XMLLNK DATA >1200) to an integer up to >FFFF. But what about the opposite action...

If I understand the E/A manual correctly, the call to XMLLNK with DATA >2300 is not available, if called from Extended Basic with CALL LINK. Is there a 'standard' solution to this problem like some other ROM routine or a piece of code, that all old hands uses?

I suppose I could store the integer in a predetermined address in MC, switch back and use CALL PEEK to get the high and low byte, and put the combined value back in a variable in Extended Basic. But getting it back as a float via the FAC seems to be the proper solution - except that the routine is not there in Extended Basic.

In XB ROM 1 is CIF 

 

  2738            ************************************************************
  2739 74AA              AORG >74AA   
  2741                
  2742            ************************************************************
  2743            * CIF     - Convert integer to floating   
  2744            *           Assume that the value in the FAC is an integer  
  2745            *            and converts it into an 8 byte floating point  

 99/4 ASSEMBLER
CIFS                                                         PAGE 0063
  2746            *            value  
  2747            ************************************************************
  2748 74AA 0204  CIF    LI   R4,FAC            Will convert into the FAC   
       74AC 834A  
  2749 74AE C014         MOV  *R4,R0            Get integer into register   
  2750 74B0 C184         MOV  R4,R6             Copy pointer to FAC to clear i
  2751 74B2 04F6         CLR  *R6+              Clear FAC & FAC+1   
  2752 74B4 04F6         CLR  *R6+              In case had a string in FAC   
  2753 74B6 C140         MOV  R0,R5             Is integer equal to zero?   
  2754 74B8 1323         JEQ  CIFRT             Yes, zero result and return   
  2755 74BA 0740         ABS  R0                Get ABS value of ARG  
  2756 74BC 0203         LI   R3,>40            Get exponent bias   
       74BE 0040  
  2757 74C0 04F6         CLR  *R6+              Clear words in result that  
  2758 74C2 04D6         CLR  *R6                might not get a value  
  2759 74C4 0280         CI   R0,100            Is integer less than 100?   
       74C6 0064  
  2760 74C8 1A13         JL   CIF02             Yes, just put in 1st fraction 
  2761            *                              part   
  2762 74CA 0280         CI   R0,10000          No, is ARG less then 100^2?   
       74CC 2710  
  2763 74CE 1A08         JL   CIF01             Yes, just 1 division necessary
  2764            *                             No, 2 divisions are necessary 
  2765 74D0 0583         INC  R3                Add 1 to exponent for 1st   
  2766 74D2 C040         MOV  R0,R1             Put # in low order word for th
  2767            *                              divide   
  2768 74D4 04C0         CLR  R0                Clear high order word for the 
  2769            *                              divide   
  2770 74D6 3C20         DIV  @C100,R0          Divide by the radix   
       74D8 6008  
  2771 74DA D920         MOVB @R1LB,@3(R4)  ~@  Move the radix digit in   
       74DC 83E3  
       74DE 0003  
  2772 74E0 0583  CIF01  INC  R3                Add 1 to exponent for divide  
  2773 74E2 C040         MOV  R0,R1             Put in low order for divide   
  2774 74E4 04C0         CLR  R0                Clear high order for divide   
  2775 74E6 3C20         DIV  @C100,R0          Divide by the radix   
       74E8 6008  
  2776 74EA D920         MOVB @R1LB,@2(R4)  ~@  Put next radix digit in   
       74EC 83E3  
       74EE 0002  
  2777 74F0 D920  CIF02  MOVB @R0LB,@1(R4)  ~@  Put highest order radix digit 
       74F2 83E1  
       74F4 0001  
  2778 74F6 D520         MOVB @R3LB,*R4         Put exponent in   
       74F8 83E7  
  2779 74FA 0545         INV  R5                Is result positive?   
  2780 74FC 1101         JLT  CIFRT             Yes, sign is correct  
  2781 74FE 0514         NEG  *R4               No, make it negative  
  2782 7500 045B  CIFRT  RT   
  2783            ************************************************************

You can access it at:

0240 6030 74AA         DATA CIF,CONTIN,RTNG,SCROLL,IO,GREAD,GWRITE,DELREP   
       6032 65CC  
       6034 6630  
       6036 7ADA  
       6038 7B48  
       603A 7EB4  
       603C 7ED8  
       603E 7EF4  
  0241            *           8    9    A      B      C      D      E   
  0242 6040 7F7E         DATA MVDN,MVUP,VGWITE,GVWITE,GREAD1,GWITE1,GDTECT  
       6042 6F98  
       6044 7FC0  
       6046 7FDA  
       6048 7EA6  
       604A 7ECA  
       604C 6050  
  0243            *           F   
  0244 604E 7C56         DATA PSCAN   
  0245                

The CIF is XB ROM 1 has to be called from GPL not from Assembly as it returns to GPL.

But you can use page Editor Assembler page 415 to see all the Extended Basic equates.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

5 hours ago, jschultzpedersen said:

But getting it back as a float via the FAC seems to be the proper solution - except that the routine is not there in Extended Basic.

My BBS software passes values back and forth between XB and assembly. Although it's been a while since I have played around with the routines, I can soundly state that CFI and CIF work via CALL LINK and the standard XB v110 cartridge. If there are exceptions, neither I nor anyone who ran the software encountered them in the past 30+ years.  Note the EQUates and the code segments below. 

 

A few things to consider:

1. The integer is a 16-bit value and I think it is also considered signed.

2. Most of my CALL LINK routines start in the GPLWS workspace (>83E0).  I don't think this is necessary since the routines are called via BLWP, but I figured I should mention it. I preserve some registers and PAD ram (8300-83ff) if I need to use it.  In this case, I don't believe that you need to preserve the FAC space.

3. If you return to XB via a simple "RT" statement, you may need to clear the status at >837C.  There are various ways to get back and hopefully, I'm not forgetting something important. :) 

4. I don't recall why I clear the status word before NUMASG. 

 

;Equates relevant to the below code

GPLWS  EQU  >83E0
NUMASG EQU  >2008
CIF    EQU  >0020
FAC    EQU  >834A
NUMREF EQU  >200C
CFI    EQU  >12B8
XMLLNK EQU  >2018

-----

;this routine converts an integer (R0) to float then returns it to XB via NUMSASG

       MOV  R0,@>834A         Put sectors into FAC
       BLWP @XMLLNK           convert to floating point
       DATA CIF               integer to floating point
       CLR  R0
       LI   R1,1              1st var
       CLR  @>837C            clear status
       BLWP @NUMASG           put sectors into 1st variable

-----

;this routine looks for a float as variable #2, retrieves it via NUMREF, then converts to integer and moves it to R0

       CLR  R0
       LI   R1,2              2nd var
       BLWP @NUMREF           get the float from XB
       BLWP @XMLLNK           
       DATA CFI               float to int
       MOV  @FAC,R0           move int to R0

 

Link to comment
Share on other sites

6 hours ago, jschultzpedersen said:

I suppose I could store the integer in a predetermined address in MC, switch back and use CALL PEEK to get the high and low byte, and put the combined value back in a variable in Extended Basic.

To your second point. LOAD/PEEK work well enough that you can use it to pass to/from assembly, so long as you have well-defined addresses and use a place that is unlikely to get corrupted. 

 

I use >A000 to >A100, making sure that my program+numeric variable space never encroach on this last 256 bytes of the memory area.  One of my program loaders passes various values such as current program, target program, colors, etc. so that (1) the assembly code can reference it and (2) all XB programs can reference and decide on proper courses of action. It's quick and dirty, and to me quite useful. 

 

(>A000 is -24576, >A001 is -24575, etc.).  In the below example, you can load value 20 into >A000, run another program, then retrieve the value. Classic99 is a good way to see what is happening with CALL LOAD.  Most of all, have fun playing and learning. 

 

100 CALL LOAD(-24576,20)

RUN "DSK1.PROGRAM"

200 CALL PEEK(-24576,A)

 

  • Like 1
Link to comment
Share on other sites

If I understand your question correctly, you want to pass a number from XB to an assembly subroutine, then convert it into an integer, do some operation on it, then convert back to floating point and return the number to XB

If so, here is a simple example of how to do this.

The assembly subroutine TEST gets NUMBER1 from XB, converts to integer, adds 99, converts to floating point, returns the number to XB as NUMBER2, then returns to XB

CALL LINK("TEST",3.14159,X)::PRINT X         (X will be 102)

 

*test of CFI and CIF
*CALL LINK("TEST",NUMBER1,NUMBER2)
*NUMBER1 IS FETCHED BY ASSEMBLY ROUTINE, CONVERTED TO INTEGER
*99 IS ADDED, CONVERTED BACK TO FLOATING, THEN RETURNED TO XB AS NUMBER2

XMLLNK	EQU >2018
NUMREF	EQU >200C
NUMASG EQU >2008
FAC	EQU >834A	
	
	DEF TEST
	
TEST	LWPI WKSP
	CLR R0
	LI R1,1	f	irst item in argument list
	BLWP @NUMREF		now number1 is in FAC as floating point	

	BLWP @XMLLNK
	DATA >12B8	CFI	now number is an integer
	
	LI R5,99
	A R5,@FAC		add 99 to integer

	BLWP @XMLLNK
	DATA >0020	CIF	number is floating point here
	
	INC R1		second item in argument list	
	BLWP @NUMASG	send the number back to XB
	
	LWPI >83E0
	B @>006A
	
WKSP	BSS 32
	
	END
	

 

  • Like 2
Link to comment
Share on other sites

Thanks for all the input. I now have a working solution that looks like this:

 

It has a float as input (43,1232). After a trip back and forth, the integer value is returned as a float (43). For good measure I stored the integer value in FAC to address >A800 before conversion back to a float as a check.

 

The part I was missing was the CIF routine. I am a bit curious about that one. I can find the CFI routine on page 51 in the TI/99 INTERN book. But I don't see the CIF routine. Can anyone point it out to me, please.

 


100 CALL INIT
110 CALL LOAD("DSK3.C8.OBJ")
120 CALL LINK("START",43.1232,A)
130 PRINT A
140 N=VAL(>"A800")
150 CALL PEEK(N,H)
160 CALL PEEK(N+1,L)
170 PRINT H;L


       DEF  START                       
                                        
NUMREF EQU  >200C                       
NUMASG EQU  >2008                       
FAC    EQU  >834A                       
CIF    EQU  >0020                       
CFI    EQU  >12B8                       
XMLLNK EQU  >2018                       
                                        
SAVR11 BSS  2                           
                                        
START  MOV  R11,@SAVR11                 
                                        
       CLR  R0                          
       LI   R1,1                        
       BLWP @NUMREF      * GET PARM1    
                                        
       BLWP @XMLLNK      * FLOAT -> INT 
       DATA CFI                         
                                        
       MOV  @FAC,@>A800  * STORE INT    
                                        
       BLWP @XMLLNK                     
       DATA CIF          * INT -> FLOAT 
.                                       
       CLR  R0                          
       LI   R1,2                        
       BLWP @NUMASG      * RETURN PARM2 
                                        
       MOV  @SAVR11,R11                 
       RT                               
       END  

Link to comment
Share on other sites

Looks like the XML TABLE, and XMLLNK, work a bit differently in XB.

In E/A, DATA >2300, takes you to the routine at >2258.

 

In XB, DATA >0020, takes you to the routine at >74AA.

   74AA  0204  li   R4,>834a              
         834A
   74AE  C014  mov  *R4,R0                
   74B0  C184  mov  R4,R6                 
   74B2  04F6  clr  *R6+                  
   74B4  04F6  clr  *R6+                  
   74B6  C140  mov  R0,R5                 
   74B8  1323  jeq  >7500                 
   74BA  0740  abs  R0                    
   74BC  0203  li   R3,>0040              
         0040
   74C0  04F6  clr  *R6+                  
   74C2  04D6  clr  *R6                   
   74C4  0280  ci   R0,>0064              
         0064
   74C8  1A13  jl   >74f0                 
   74CA  0280  ci   R0,>2710              
         2710
   74CE  1A08  jl   >74e0                 
   74D0  0583  inc  R3                    
   74D2  C040  mov  R0,R1                 
   74D4  04C0  clr  R0                    
   74D6  3C20  div  @>6008,R0             
         6008
   74DA  D920  movb @>83e3,@>0003(R4)     
         83E3
         0003
   74E0  0583  inc  R3                    
   74E2  C040  mov  R0,R1                 
   74E4  04C0  clr  R0                    
   74E6  3C20  div  @>6008,R0             
         6008
   74EA  D920  movb @>83e3,@>0002(R4)     
         83E3
         0002
   74F0  D920  movb @>83e1,@>0001(R4)     
         83E1
         0001
   74F6  D520  movb @>83e7,*R4            
         83E7
   74FA  0545  inv  R5                    
   74FC  1101  jlt  >7500                 
   74FE  0514  neg  *R4                   
   7500  045B  b    *R11   

...Not too sure where the routine ends...

:ponder:

Link to comment
Share on other sites

I have looked and learned and proceeded to testing GPLLNK to be able to return a value as a string. There are some oddities here, I think...See below. Here is the code used for testing:

 


100 CALL INIT
110 CALL LOAD("DSK3.C4.OBJ")
120 CALL LINK("START",1234,A$)
130 PRINT A$;LEN(A$)


       DEF  START                       
                                        
NUMREF EQU  >200C                       
STRASG EQU  >2010                       
STATUS EQU  >837C                       
FAC    EQU  >834A                       
FAC11  EQU  >8355                       
FAC12  EQU  >8356                       
PAD    EQU  >8300                       
                                        
SAVR11 BSS  >02                         
TXTBUF BSS  >10                         
                                        
START  MOV  R11,@SAVR11                 
                                        
       CLR  R0           * PARM1 -> FAC 
       LI   R1,1                        
       BLWP @NUMREF                     
                                        
       CLR  R0           * CONV FAC ->  
       MOVB R0,@FAC11    * STRING       
       MOVB R0,@STATUS                  
       BLWP @GPLLNK                     
       DATA >14                         
                                        
       LI   R1,PAD       * CALC STRING  
       A    @FAC11,R1    * LOCATION     
                                        
       LI   R2,TXTBUF    * COPY STRING  
       MOVB @FAC12,R3    * TO TXTBUF    
LOOP   MOVB *R1+,*R2+                   
       DEC  R3                          
       JNE  LOOP                        
                                        
       MOVB @FAC12,R4    * SET LEN BYTE               
       SWPB R4           * FOR TXTBUF              
       DEC  R4           * STRING TO           
       SWPB R4           * @FAC12-1               
       MOVB R4,@TXTBUF                  
                                        
       CLR  R0           * STRING ->    
       LI   R1,2         * PARM2        
       LI   R2,TXTBUF                   
       BLWP @STRASG                     
                                        
       MOV  @SAVR11,R11                 
       RT                               
                                        
       COPY "DSK3.GPLLNK" * INCL GPLLNK 
       END

 

 

As far as I can see, the GPLLNK >14 routine only accepts positive integers with a size of max 10. A minus sign is ignored. It returns the absolute value. The length byte in @FAC12 returns a number that is 1 byte higher than the actual length. This has the effect of adding a null byte to the string, that is returned, unless the value is decremented before being inserted as byte 1 in the string.

 

Is my code faulty in some way despite giving the right result, or am I using a dubious version of GPLLNK, or is this just life as we know it?

Link to comment
Share on other sites

Posted (edited)

I see one error in your code:

       LI   R1,PAD       * CALC STRING  
       A    @FAC11,R1    * LOCATION     

 

FAC11 is an odd address, so I think   A @FAC11,R1 really does A @FAC10,R1

Various ways to handle this. One would be:

CLR R1

MOVB @FAC11,R1

SWPB R1

AI R1,>8300

 

LI R1,>0083

MOVB @FAC11,R1

SWPB R1

 

or

LI R1,PAD

AB @FAC11,@WKSP+3

Here you need to know the workspace, which is a good thing to know anyway.

 

My notes do not show any of the problems you report.

I can test some tonight. Are you using this with XB. EA basic, or MiniMem basic?

Edited by senior_falcon
  • Like 3
Link to comment
Share on other sites

Posted (edited)
21 hours ago, jschultzpedersen said:

As far as I can see, the GPLLNK >14 routine only accepts positive integers with a size of max 10. A minus sign is ignored. It returns the absolute value. The length byte in @FAC12 returns a number that is 1 byte higher than the actual length. This has the effect of adding a null byte to the string, that is returned, unless the value is decremented before being inserted as byte 1 in the string.

 

Is my code faulty in some way despite giving the right result, or am I using a dubious version of GPLLNK, or is this just life as we know it?

 

GPL routine >0014 does not convert integer to string, it converts number to string, i.e., floating-point, radix-100 numbers to string. If a number happens to be an integer, the limit is imposed by the TI radix-100 format, which can be in the 10-128..10127 range. The routine can also handle negative numbers just fine for TI Basic format, which is what you requested of the routine by setting FAC11 = 0. In addition to the error discovered by @senior_falcon, this code also needs work:

       LI   R2,TXTBUF    * COPY STRING  
       MOVB @FAC12,R3    * TO TXTBUF    
LOOP   MOVB *R1+,*R2+                   
       DEC  R3                          
       JNE  LOOP                        

 

You must get the contents of FAC12 to the LSB (Least Significant Byte) of R3 and insure the MSB is 0. Otherwise DEC R3 will not work properly. Also, the length you need to copy is FAC12+1 to include the length byte. You can do that as follows:

       LI   R2,TXTBUF    * COPY STRING  
       MOVB @FAC12,R3    * TO TXTBUF 
       SRL  R3,8         * shift count to LSB, zeroing MSB <─── add this instruction
LOOP   MOVB *R1+,*R2+                   
       DEC  R3                          
       JNE  LOOP                        

 

I also don’t think you should change the string length for passing back to XB.

 

...lee

Edited by Lee Stewart
correction
  • Like 1
Link to comment
Share on other sites

This makes me wonder how many copies of this little loop or something similar are littered about the TI99 system. 

I suppose I could do my own search in the ROMs.

hmm...

 

LOOP   MOVB *R1+,*R2+                   
       DEC  R3                          
       JNE  LOOP  

 

Link to comment
Share on other sites

Thanks for the advice. Tomorrow is another day, and I'll se what I can do with the improvements. I am using XB3 and the assembler, that comes with it, mainly because XB3 has that nice VAL(>"hexvalue") command, that helps when peeking addresses from basic. Also it means that I can switch between Basic mode and EA mode quickly by resetting to boot mode and selection either option 2 or 3.

Link to comment
Share on other sites

Posted (edited)

Now I see what is going wrong. I had one part of the answer, Lee had another, but wait, there's more.

Here is your code:

   LI   R1,PAD       * CALC STRING  
       A    @FAC11,R1    * LOCATION     
                                        
       LI   R2,TXTBUF    * COPY STRING  
       MOVB @FAC12,R3    * TO TXTBUF    
LOOP   MOVB *R1+,*R2+                   
       DEC  R3                          
       JNE  LOOP                        
                                        
       MOVB @FAC12,R4    * SET LEN BYTE               
       SWPB R4           * FOR TXTBUF              
       DEC  R4           * STRING TO           
       SWPB R4           * @FAC12-1               
       MOVB R4,@TXTBUF            

 

This should be: (I did not test this so there might be an error)

        LI R1,>0083       pad with bytes reversed

        MOVB @FAC11,R1

        SWPB R1           now R1 points to string

 

        LI R2,TXTBUF

        MOVB @FAC12,R3     now length is in MSB of R3

        MOVB R3,*R2+          put length byte at beginning of TXTBUF

 

        SRL R3,8                   now length is in LSB of R3 and can use as a counter

LOOP MOVB *R1+,*R2+

        DEC R3

        JNE LOOP

 

Also, you do not need to store R11 and then restore it.

As a side note, I do not like the use of RT because I feel it obscures what is actually happening. For me, B *R11 is much clearer. If you needed to store R11, you could MOV R11,R10 and when it is time to return just B *R10

Edited by senior_falcon
  • Like 2
Link to comment
Share on other sites

Thanks for hints and advices. Based on those I have rewritten my code, and it works well - also when including decimals. One thing though. It still insists on returning an extra character at the end of the returned string. Perhaps it includes the length byte at the front when counting its length. I have not compensated for this in my code. You can see the problem if you run the basic code. Or see picture.


80 CALL CLEAR
90 V1=1234500001
100 CALL INIT
110 CALL LOAD("DSK3.C7.OBJ")
120 CALL LINK("START",V1,V2,A$)
130 PRINT "NUMBER :";V1: :"LENGTH BYTE:";V2
140 A=VAL(>"A000"):: PRINT :"CONTENT OF TXTBUF INCLUDING LEN BYTE :"
150 FOR I=A TO A+V2-1
160 CALL PEEK(I,V):: PRINT V;
170 NEXT I
180 PRINT : :"STRING RETURNED :":">";A$;"<"

       DEF  START                       
                                        
STATUS EQU  >837C                       
NUMASG EQU  >2008                       
NUMREF EQU  >200C                       
STRASG EQU  >2010                       
FAC    EQU  >834A                       
FAC11  EQU  FAC+11                      
FAC12  EQU  FAC+12                      
STRBUF EQU  >A000                       
CIF    EQU  >0020                       
XMLLNK EQU  >2018                       
                                        
SAVR11 BSS  2                           
                                        
START  MOV  R11,@SAVR11                 
                                        
       CLR  R0           * PARM1 -> FAC 
       LI   R1,1                        
       BLWP @NUMREF                                                                              
                                      
       MOVB R0,@FAC11    * FAC -> STRING
       MOVB R0,@STATUS                  
       BLWP @GPLLNK                     
       DATA >14                         
                                        
       CLR  R3           * FAC12 -> FAC 
       MOVB @FAC12,R3                   
       SWPB R3                          
       MOV  R3,@FAC                     
                                        
       BLWP @XMLLNK      * ARG TO FLOAT 
       DATA CIF                         
                                        
       CLR  R0           * ARG -> PARM2 
       LI   R1,2                        
       BLWP @NUMASG                     
                                        
       LI   R1,>0083     * CALC STR ADR 
       MOVB @FAC11,R1                   
       SWPB R1                          
                                        
       LI   R2,STRBUF                   
                                        
       CLR  R3           * LEN->LOOPNO  
       MOVB @FAC12,R3                   
       SWPB R3                          
                                        
LOOP2  MOVB *R1+,*R2+    * STR TO STRBUF
       DEC  R3                          
       JNE  LOOP2                       
                                        
       MOVB @FAC12,R3    * UPDATE LEN BYTE               
       MOVB R3,@STRBUF                  
                                        
       CLR  R0           * STRING -> PARM3               
       LI   R1,3                        
       LI   R2,STRBUF                   
       BLWP @STRASG                     
                                        
       MOV  @SAVR11,R11                 
       RT                               
                                        
       COPY "DSK3.GPLLNK"               
       END 

dump.png

Link to comment
Share on other sites

Posted (edited)

I haven't totally worked through your program, but I'm pretty sure what is happening is that you are moving the 11 bytes of the string to the buffer at >A000, then writing the length byte to the first byte of the buffer. I believe there is a leading space in the string that you are overwriting with the length byte. I bet if you make the number negative, you will overwrite the minus sign and it will look like a positive number.

You are moving the first byte of the string to >A000. It should be at >A001, with the length byte at >A000.

Try it my way and I bet it works.

 

As a side note, once you do the number to string conversion, move it into the buffer as soon as possible. The string is somewhere in the scratchpad, and who know what memory areas are used when you do the XMLLNK and the NUMASG. They could easily corrupt the string

 

Edited by senior_falcon
  • Like 1
Link to comment
Share on other sites

2 hours ago, jschultzpedersen said:

One thing though. It still insists on returning an extra character at the end of the returned string. Perhaps it includes the length byte at the front when counting its length. I have not compensated for this in my code. You can see the problem if you run the basic code. Or see picture.

 

I figured out what is happening. With FAC11 set to 0, the returned string is in TI Basic format, which has a place for the sign. This is a space (32) for positive numbers and a  dash (45) for negative numbers. I see that @senior_falcon agrees with that analysis. You should put the unaltered count byte ahead of the actual string by doing what @senior_falcon earlier suggested with

       MOVB @FAC12,*R2+

 

ahead of copying the actual string.

 

Also, you do not need to invoke GPLLNK to get CNS. You can use XMLLNK with the same arguments as follows:

CNS    EQU  >0006
* ...
       BLWP @XMLLNK
       DATA CNS

 

...lee

  • Like 1
Link to comment
Share on other sites

20 hours ago, jschultzpedersen said:

Thanks for the advice. Tomorrow is another day, and I'll se what I can do with the improvements. I am using XB3 and the assembler, that comes with it, mainly because XB3 has that nice VAL(>"hexvalue") command, that helps when peeking addresses from basic. Also it means that I can switch between Basic mode and EA mode quickly by resetting to boot mode and selection either option 2 or 3.

RXB has a similar command but way more useful. (The XB3 version can go to out of range values above 32768 and crash)

 

CALL HEX(hex-string$,numeric-variable)

or

CALL HEX(numeric-variable,hex-string$)

 

This RXB subroutine command is specifically designed for CALL LINK or CALL LOAD or CALL PEEK or CALL MOVES or working with Assembly.

  • Like 1
Link to comment
Share on other sites

Yes... Now it works all the way. Thanks! That space character in the first position fooled me. I thought it made room for the length byte, so I could add it. The correct return string has a space or minus sign in front of the characters representing the numbers. I also learned something about the behaviour and use of single byte instructions in odd addresses. It has been a good day 😀

 

I changed a few lines in this part of the code as recommended... and, as you say, I can use XMLLNK >0006 instead of the GPLLNK >14 call

 

       LI   R1,>0083     * CALC STR ADR 
       MOVB @FAC11,R1                   
       SWPB R1                          
                                        
       LI   R2,STRBUF                   
                                        
       CLR  R3           * LEN->LOOPNO  
       MOVB @FAC12,R3                   
                                        
       MOVB R3,*R2+                     
                                        
       SWPB R3                          
                                        
LOOP2  MOVB *R1+,*R2+    * STR TO STRBUF
       DEC  R3                          
       JNE  LOOP2

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Yes, I used 

 

CLR R0

MOVB R0,@FAC11

MOVB R0,@STATUS

BLWP @XMLLNK

data CNS

 

where CNS EQU >0006

 

I have no docs on CIF and CNS. So I cannot say if I use them correctly. But the code works.

 

 

 

Edited by jschultzpedersen
error in answer
  • Like 3
Link to comment
Share on other sites

Perhaps a bit off topic, but still... it is about converting stuff.... Just for fun I coded this little routine, that converts any reasonably sized integer to a string with its unsigned hex value in Basic. S is the format length of the string (not counting a minus sign ahead of it). N is the number to be converted. Precalculating values for P to an array and indexing into that would speed up the routine, since 'power up' is slow. S must be large enough to cope with the number, or you will only get a partial answer.

 


100 N=-32000 :: V$=""
110 S=8 :: S$="0123456789ABCDEF"
120 PRINT N;"ER LIG: ";
130 IF N<0 THEN V$="-" :: N=ABS(N)
140 V$=V$&">"
150 FOR I=(S-1)*4 TO 0 STEP -4
160 P=2^I :: V=INT(N/P):: N=N-V*P
170 V$=V$&SEG$(S$,V+1,1)
180 NEXT I
190 PRINT V$

Untitled.png

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...