jschultzpedersen Posted May 16 Share Posted May 16 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. 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 16 Share Posted May 16 (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 May 16 by senior_falcon Quote Link to comment Share on other sites More sharing options...
Gary from OPA Posted May 16 Share Posted May 16 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 5 Quote Link to comment Share on other sites More sharing options...
RXB Posted May 16 Share Posted May 16 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. 1 1 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 17 Share Posted May 17 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 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted May 17 Share Posted May 17 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) 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 17 Share Posted May 17 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 2 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 17 Author Share Posted May 17 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 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted May 17 Share Posted May 17 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... Quote Link to comment Share on other sites More sharing options...
apersson850 Posted May 17 Share Posted May 17 If you look at page 23 in this issue of the newsletter Programbiten, then you can see how I used both conversions there. 1 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 21 Author Share Posted May 21 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? Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 22 Share Posted May 22 (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 May 22 by senior_falcon 3 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 22 Share Posted May 22 (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 May 22 by Lee Stewart correction 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 22 Share Posted May 22 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 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 22 Author Share Posted May 22 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. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 22 Share Posted May 22 (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 May 22 by senior_falcon 2 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 23 Author Share Posted May 23 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 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 23 Share Posted May 23 (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 May 23 by senior_falcon 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 23 Share Posted May 23 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 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted May 23 Share Posted May 23 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. 1 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 23 Author Share Posted May 23 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 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted May 23 Share Posted May 23 "I can use XMLLNK >0006 instead of the GPLLNK >14 call" Is this XMLLNK available in XB? 1 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 24 Author Share Posted May 24 (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 May 24 by jschultzpedersen error in answer 3 Quote Link to comment Share on other sites More sharing options...
jschultzpedersen Posted May 25 Author Share Posted May 25 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$ 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted May 27 Share Posted May 27 Except that the concept of minus signs is normally not used with hexadecimal notation. There's not any -7D00, but it's 8300 instead. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.