Jump to content
IGNORED

A worse programmers questions


Sid1968

Recommended Posts

As for "Why use compiled BASIC when C, Pascal, or Assembler give 10x faster results?"

 

Again, Intellectual barrier to entry.  Emphasis on "Beginner's" in the name.

 

If you have gotten so good at BASIC that you now NEED to control execution at the bare metal to attain maximal speed, you are ready to graduate; you understand program flow well enough to move to something more powerful, but more challenging to use-- Where previously, you started at the bottom of the learning curve, and would have been completely intimidated or overwhelmed by using the more advanced tools straight off.

 

For many things, a compiled BASIC version would be just fine.  If we look at the claims of the TI basic compiler, with its claim of "30x speed increase", if you wrote a game that ran at 1fps in the interpreter, it would then run at a sprightly 30fps after compilation.  It is when you compile your game, and it still runs at 15fps or slower, and you go "Shit--- Surely there is something FASTER?" that you start looking for a better tool, and rightly-- SHOULD be looking for a better tool.  Before then though, since you are a beginner, you will look into how to optimize your program to squeeze every last iota of performance out, which is good practice for when you graduate to the better languages.

 

BASIC is a milestone on the road to being a good programmer. Not the destination.  However, giving a full toolset to develop all the needed skills, while still being inferior to the better but harder to use languages, gives motivation to graduate, which would be a feature, not a drawback.  You are SUPPOSED to move away from BASIC.

 

 

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

I think part of the disconnect is that the BASIC's on other systems besides the TI were... how to say this... Pretty fast and loose.

 

Both the Apple and Commodore used POKE and PEEK to access most of the specific hardware, such as video and sound, and otherwise implemented a very simple ANSI BASIC flavor for logic and control. TI BASIC was crafted specifically for users who had never used a computer before, which is one reason accessing assembly and machine language is nearly impossible. TI Extended BASIC is probably the most equitable to other BASICS on contemporary systems, and it's clear part of it was designed to overcome various limitations and optimization problems over the console BASIC.

 

The TRS-80 Coco blows everyone out of the water though on print speed; if you list a program it flies on the screen SO FAST it's a blur and you can't discern almost anything. Their solution? Implement a pause feature. Their BASIC also allowed huge lines and stuff like FOR loops in conditionals, using a NEXT without a variable as a general terminator.

 

I write Wizard's Doom using machine language extensions because I needed the performance but I wanted to keep it in Extended BASIC like the original games. The technical challenge was interesting and considerable. Now I'm pretty much focused on assembly language because I'm more interested in pushing the limits on the actual machine itself rather than the platform.

 

 

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

On 9/27/2019 at 4:40 PM, Sid1968 said:

1. For programming what applications was fbForth made for?

2. What is the difference between Forth and fbForth?

 

Forth was invented in 1970 by Charles Moore to help control radio telescopes. As to the nature of Forth, there is this from the Forth Interest Group   website  :

 

What is Forth?

  • Forth is a stack-based, extensible language without type-checking. It is probably best known for its "reverse Polish" (postfix) arithmetic notation, familiar to users of Hewlett-Packard calculators. Forth is a real-time programming language originally developed to control telescopes. Forth has many unique features and applications:
  • Forth can compile itself into a new compiler!
  • Reverse-polish coding.
  • Edit time error checking and compiling (similar to BASIC).
  • Extremely efficient thread based language.
  • Can be used to debug itself!
  • Extensible, thus can become what ever you need it to be.
  • Many freeware implementations are available.
  • Many commercial applications: language translators, animation (movies, DisneyLand), hard disk controllers.

fbForth is a dialect of Forth. It is based on TI Forth, both of which were developed specifically for the TI-99/4A computer from figForth (see above Forth Interest Group website). If you are interested in the differences between fbForth 2.0 and TI Forth, see “Since TI Forth” on my fbForth website.

 

As to the answer to your first question, You can write pretty much any application you wish for the TI-99/4A. You can do anything with the TI-99/4A that you can do in any other computer language on the TI-99/4A, including Assembly Language.

 

...lee

  • Thanks 2
Link to comment
Share on other sites

4 minutes ago, Lee Stewart said:

 

Forth was invented in 1970 by Charles Moore to help control radio telescopes. As to the nature of Forth, there is this from the Forth Interest Group   website  :

 

What is Forth?

  • Forth is a stack-based, extensible language without type-checking. It is probably best known for its "reverse Polish" (postfix) arithmetic notation, familiar to users of Hewlett-Packard calculators. Forth is a real-time programming language originally developed to control telescopes. Forth has many unique features and applications:
  • Forth can compile itself into a new compiler!
  • Reverse-polish coding.
  • Edit time error checking and compiling (similar to BASIC).
  • Extremely efficient thread based language.
  • Can be used to debug itself!
  • Extensible, thus can become what ever you need it to be.
  • Many freeware implementations are available.
  • Many commercial applications: language translators, animation (movies, DisneyLand), hard disk controllers.

fbForth is a dialect of Forth. It is based on TI Forth, both of which were developed specifically for the TI-99/4A computer from figForth (see above Forth Interest Group website). If you are interested in the differences between fbForth 2.0 and TI Forth, see “Since TI Forth” on my fbForth website.

 

As to the answer to your first question, You can write pretty much any application you wish for the TI-99/4A. You can do anything with the TI-99/4A that you can do in any other computer language on the TI-99/4A, including Assembly Language.

 

...lee

 

Thank you Lee. Why does FIG FORTH REL 2.0 do not know the "FDROP" Command? (Post #201)

Link to comment
Share on other sites

1 minute ago, Sid1968 said:

Thank you Lee. Why does FIG FORTH REL 2.0 do not know the "FDROP" Command? (Post #201)

 

Since I do not know what figForth release 2.0 is, I can only say that it would be that FDROP is not defined in that language. If it is related to TI Forth, it may only need to load the blocks (screens) that contain the floating point library (FPL). That is the way TI Forth handled it, i.e., the FPL is not part of the resident dictionary as it is in fbForth 2.0.

 

By the way, FDROP merely drops 4 cells (8 bytes, the size of a floating point number) from the stack and is defined as follows:

: FDROP  ( f -- )
    DROP DROP DROP DROP  ;

 

...lee

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

Have I mentioned recently that I really really love forth. Oh, then excuse me! 

I just got up from a forth issue I was dealing with to read up on this forum, then I'll be back at my forth desktop again.

I really love forth. I also love ramdrives.

Lol. Ok..I saw that someone mentioned forth and it got my attention. But Lee is so very right on the money.

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

weird w - you don't want or need those handrails once you are finished with a program.  Compiling it is what you do when you are done with the interpreter, and want something fast and reliable.

Exactly right. you do your programming in Extended BASIC with all the error checking and easy to modify program lines. THEN you compile once it all works properly.

Weird_w - For many things, a compiled BASIC version would be just fine.  If we look at the claims of the TI basic compiler, with its claim of "30x speed increase", if you wrote a game that ran at 1fps in the interpreter, it would then run at a sprightly 30fps after compilation.  It is when you compile your game, and it still runs at 15fps or slower, and you go "Shit--- Surely there is something FASTER?" that you start looking for a better tool, and rightly-- SHOULD be looking for a better tool.

As an example of compiled XB, take a look at Engine256. It runs pretty fast although it is pretty much at the limits for compiled BASIC. But when it comes to raw speed, the better tool here is assembly. Period. Compiled BASIC, Forth, GPL are all threaded code which run pretty fast but nothing like assembly. I think forth and compiled basic run at similar speeds. 

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

16 hours ago, senior_falcon said:

I get other values then zero. Floatingpointvalues smaller then 1.

 

This is true in XB which uses floating point numbers. The integer math of the compiler makes RND = 0. The only way to get a useful RND when compiled is to multiply RND by a number. You get INT(RND*100) in my example. So to compare the two fairly, mine needs to multiply RND by something and the actual XB does not. Without the x100 it takes 2 seconds.

Thank you senior_falcon for your explanation. But to be totally fair, if your compiler cant run the testprogram,

 

10 FOR I=1 TO 3000
20 A=RND
30 NEXT I
40 PRINT A

 

because it would make of floatingpoints between 0 and 1 always 0, because it cant handle floatingpoint values, your compiler pwnd by the others.

 

Your Testprogram

 

10 FOR I=1 TO 3000
20 A=RND*100
30 NEXT I
40 PRINT A

 

would be another test, that we can run maybe too.

 

Nobody can change a testprogramm only because it wont run correctly on its interpreter/compiler. Running not correctly or good enough is a result too! ;-)

Take it sporty or run the testprogram without the compiler if it could not handle floatingpoint.

Edited by Sid1968
Link to comment
Share on other sites

6 hours ago, Sid1968 said:

Lee, can you please translate the test program to fbForth 2.0?


10 FOR I=1 TO 3000
20 A=RND
30 NEXT I
40 PRINT A

Kind Regards

Sid

There are 3 pseudo-random-number words in fbForth 2.0:

  • RNDW <--generates an unsigned, pseudo-random, integer u such that 0 ≤ u ≤ 65535 (FFFFh)
  • RND   <--with a limit number n1 on the stack, generates a positive, pseudo-random, integer n2 such that 0 ≤ n2 < n1
  • FRND <--generates an unsigned, pseudo-random, floating-point number f such that 0 ≤ f < 1

The following words use each of the above in turn:

DECIMAL
: USE_RNDW  ( -- )
   0              \ put dummy number on stack to set up DROP in loop
   3000 0 DO      \ loop 3000 times
      DROP        \ drop number from top of stack
      RNDW        \ generate unsigned, pseudo-random integer u
   LOOP
   U.  ;          \ print unsigned integer left on stack

: USE_RND   ( n -- )
   0              \ put dummy number on stack to set up DROP in loop
   3000 0 DO      \ loop 3000 times
      DROP        \ drop number from top of stack
      DUP         \ dup n for next time through loop
      RND         \ generate positive, pseudo-random integer 0≥prn<n
   LOOP
   .              \ print positive integer left on stack
   DROP  ;        \ drop leftover n

: USE_FRND  ( -- )
   0 0 0 0        \ put dummy, 4-cell, FP 0 on stack to set up FDROP in loop
   3000 0 DO      \ loop 3000 times
      FDROP       \ drop FP number from top of stack
      FRND        \ generate positive, pseudo-random FP number 0≥f<1
   LOOP
   F.  ;          \ print FP number left on stack

Execution times are

  • USE_RNDW     <1 second
  • USE_RND          1 second
  • USE_FRND        4 seconds

...lee

Edited by Lee Stewart
Corrected stack effects.
  • Thanks 1
Link to comment
Share on other sites

18 hours ago, Sid1968 said:

 

 

Your Testprogram

 

10 FOR I=1 TO 3000
20 A=RND*100
30 NEXT I
40 PRINT A

 

would be another test, that we can run maybe too.

 

Nobody can change a testprogramm only because it wont run correctly on its interpreter/compiler. Running not correctly or good enough is a result too! ;-)

Take it sporty or run the testprogram without the compiler if it could not handle floatingpoint.

I disagree with this. For example, let's flip a coin in BASIC

10 IF RND<.5 THEN 30

20 PRINT "HEADS"

30 PRINT "TAILS"

Since the integer math of the compiler would always print "TAILS" you would change line 10 to:

10 IF RND*2=0 THEN 30 ! will be either 0 or 1

20 PRINT "HEADS"

30 PRINT "TAILS"

This adds a step (multiply x 2). This is hardly cheating, since it slows down the code, but it would be necessary in a program. The results speak for themselves: 3 seconds vs 50 seconds

  • Like 2
Link to comment
Share on other sites

That's always something you need to do, if you want to port a program from one language to another. You have to take into account the limitations and capabilities of the language you are going to. Otherwise you may get completely misleading results, when you don't use the good features of the new language.

This also makes comparing languages more difficult. I'm of the opinion you have to look at the entire development environment when you evaluate them, not just a few isolated features, that are proven by some small test program.

 

To return to some questions asked before, Cortex BASIC doesn't use GPL as far as I know. Why would they?

The main reasons for using an intermediate language is compactness and/or portability. The UCSD p-system does use p-code as an intermediate language. This was done to provide portability at a time when a program on one computer never would run on another. By compiling Pascal programs to p-code, which then was executed by a comparatively simple interpreter on the target machine, they could make compiled code portable between completely different machines. This was an amazing feat in the 1970's. Today, when "everybody" uses computers with the same architecture, there's no advantage to this. It's the default.

 

When it comes to GPL, I do imagine that it was developed to make the programs smaller, in the limited memories of the time. I've seen some reference somewhere to that TI had some thoughts about developing a CPU, which would run GPL as its native language. It never happened, as far as I know. TI Extended BASIC is pretty feature-rich. Named subprograms, for example, are very rare in BASIC dialects. The Cortex also implements quite a lot of hardware. That was the design philosophy behind it. I've never used any, but I read a lot about it, and stole some ideas for the computerised instruments I designed and built many years ago.

 

When it comes to the different CPU models TI manufactured, they have different performance. The TMS 9900 has it's heritage in the TI 990 mini computer line. The first in that series, the TI 990/9, implemented a memory-to-memory architecture in a CPU, built by several TTL components across several circuit boards. TI used it's top notch IC knowledge (at least at that time) to integrate the whole TI 990/9 architecture on a single chip, the TMS 9900. It was used in several lower-end TI 990 minicomputers, like the TI 990/4 and TI 990/5. The much more advanced successor TMS 99000 was used in the TI 990/10A.

Another successor to the TMS 9900, the TMS 9995, was designed to be easier to implement. It's equipped with an 8-bit wide data bus, compared to the 16 bits in the TMS 9900. This made it possible to use a 40 pin package, instead of the huge 64 pin DIL used by the TMS 9900. Internally it was still a 16 bit CPU, implementing the same instructions as the TMS 9900, and a few more. It also has a few more hardware features, and doesn't require a separate clock chip (TIM 9904).

To compensate for the narrower data bus, the TMS 9995 has about 256 bytes of on-chip memory, much like the whole TI 99/4A computer has 256 bytes of fast RAM in the computer, but outside the CPU. The on-chip memory in the TMS 9995 is 16 bits wide, of course.

TMS 9995 is a more efficient design. This is partly due to being able to do more in one clock cycle and partly due to that it implements a single-level pipeline. Where the TMS 9900 typically accesses memory in a cycle, does internal processing in the next, accesses memory again, does more internal processing and so on, the TMS 9995 accesses memory in almost every single CPU cycle. Except for when executing more advanced instructions, like MPY or DIV, the TMS 9995 is fast enough to either read a new operand or write an obtained result all the time. This means that if the TI 99/4A would have been designed around the TMS 9995 instead, that alone would have given it a higher capacity. You can compare with the Myarc Geneve, which does use the TMS 9995. But that chip didn't exist yet, when the TI 99/4 was designed.

 

This means that if you want to, there is no difference between TMS 9900 and TMS 9995 software. But to make the most of the TMS 9995, you have to make sure you put your workspace, frequently addressed data and, sometimes, frequently executed code, in the internal memory on the chip. And no, it's not in the same place as the fast memory in the TI 99/4A.

Also, if you do math, you may need to rewrite the code to use the DIVS and MPYS instructions in the TMS 9995, instead of just using DIV and MPY (the instructions the TMS 9900 supports), and then handle the sign separately, with a multiple of other instructions.

 

The TMS 9995 was the CPU I used in the instruments I built, a long time ago. I still have some vintage TMS 9995 chips in a box. That's why I know it so well.

 

TMS 9995

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

Unfortunately, we do not have similar in-depth information of the 9995 as for the 9900 ("9900 Family Systems Design"), at least none that I am aware of. The documents for the 9900 list all the microprograms line-by-line. However, what we know, beside the points you mentioned above, is that the 9900 defines machine cycles as two clock cycles, where the machine cycle and the clock cycle of the 9995 are equal. This already results in a tremendous speed-up. Consider "A R0,R1" with R0 and R1 in on-chip memory. The table says it only has 4 cycles; this already takes the prefetch into account. Typically you have six steps at least:

 

- Fetch instruction

- Decode instruction

- Fetch source

- Fetch destination

- Perform operation

- Store result

 

In fact, the fetch (n) is done in parallel to perform operation (n-1), and decode (n) runs in parallel to store result (n-1). With 4 cycles, you get an execution time of 4*0.333 µs = 1.332 µs. The 9900 requires 7 machine cycles: 5 microprogram steps plus 1 cycle for each source and destination fetch, which means 14 clock cycles, which yields an execution time of 4.662 µs. Quite a difference.

 

Specs say that the external 12 MHz clock is divided by 4 and then fed to ALU etc. Since there is so much running in parallel, I wonder whether the 12 MHz clock input is actually used for the microprogram interpreter, and then divided by 4 for the actual machine cycle and for CLKOUT. Another point is that TI changed the previous "Data derivation sequence" of the 9900 to an "Address derivation sequence" of the 9995. The important difference is that the DDS of the 9900 makes it always pull destination data even when they are not used (e.g. when you do a MOV, the 9900 processor actually fetches the destination word, just to overwrite it in the next cycle). The ADS requires a following value fetch instead, but this is more efficient in many cases.

 

Also, the 8 lines of the data bus made it actually possible to drop the read-before-write completely because you could now change single bytes in memory.

 

As I said some time ago, this was not so unusual; remember the Intel 8088 (16 bit architecture) which also has 8 data lines only.

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

9 hours ago, apersson850 said:

 

 

 

TI Extended BASIC is pretty feature-rich. Named subprograms, for example, are very rare in BASIC dialects.

 

 

All about CALLs in 990 TI BASIC

The CALL syntax, in 99/4A BASIC and Extended Basic, matches the syntax used in TI BASIC for the 990 minicomputer.  So TI BASIC was designed for named subprograms well before the 99/4A. 

 

It's clear to me that the 99/4A TI BASIC and Extended BASIC were a deliberate subset of 990 TI BASIC with few differences. While reading about the CALL syntax, I also read that 990 TI BASIC used RADIX 100 (with an important feature for DECIMAL type.)


I played with 990 TI BASIC yesterday on Dave Pitt's excellent 990 simulator with DNOS. Basic is already installed. However, it is not clock-speed accurate (it runs fast) so timing BASIC benchmarks is silly. https://www.cozx.com/dpitts/ti990.html


 

In the TI BASIC Reference Manual, 1-Dec-83:  http://www.bitsavers.org/pdf/ti/990/basic/


Page 9-3 describes the DEF statements, which may have a return type, or be multi-line.

Page 9-5 describes the CALL/SUB/SUBEND statements.

Page 11-6 describes how to CALL assembly language routines from 990 TI BASIC, and explains the Radix 100 format of parameters.

 

The CALL/SUB statements, which may have variable types declared:

 

SUB HSTEP(REAL A, INTEGER B, REAL C)
IF A=0 THEN SUBEXIT
C = A * 2^(B/12)
SUBEND

REAL X = 220
INTEGER N = 5
REAL Y
CALL HSTEP(X, N, Y)

An optional type after SUB can set one type for all parameters.

 

ESUB is used instead of SUB to write subroutines that have external visibility. The ESUBs are callable from other programs.


Page 9-3 describes the DEF statements, which may have types or be multi-line:

DEF AVG(X,Y) = (X+Y)/2
DEF REAL PI = 3.1415926535

X = AVG(A,B)/PI

or

DEF XYZ(A,B,C)
XYZ = A + B + 2
FNEND


One of TI's examples of a multi-line DEF is the square root algorithm (also explained to students in TI Learning Center's DC AND BASIC ELECTRICITY textbook.)

 

CALL assembly


Section 11-6 describes how to add assembly language routines to 990 TI BASIC and explains the Radix 100 format.

 

Calling assembly routines is not like  99/4A TI BASIC:

 

LIBRARY "*pathname"
CALL ".ASMBLY"(A$, A, B, C)

where pathname is your assembled and linked code, for example .BSCSUP. The * indicates that the routine should persist in memory.  

 

The first two words of the file are a BLWP vector; BASIC overwrites the workspace pointer at load time.  Assembly subroutines return with RTWP. Important assembly libraries distributed with TI BASIC were the .SORT library and keyed file database.

 

BASIC parameters are passed to the assembly routine in a 18-word block of memory:

 

Continuing the example:

 

REAL A
INTEGER B,C
CALL ".ASMBLY"(A$, A, B, C)

WP-36 Number of parameters
WP-34 2 bits for each parameter type: 
00 end of list
01 integer
10 real or decimal
11 string
WP-30 pointers ...

For the example above,

 

>0004
>E500  * b'11100101 00000000 codes for string, real, int, int
>0000
ptr to A$
ptr to A
ptr to B
ptr to C
>0000
...

Figure 11-1 goes on to unpack the variable formats in memory. In particular, it describes RADIX-100 format for REAL. Integers are 16 bits.

 

REALs are stored in the quite familiar 99/4A format. As we know, the mantissa bytes range from 0-99, wasting a bit per byte (1.3 bits to be pedantic). TI BASIC represents type DECIMAL by using 6 leftover bits to store the number of significant decimal places! (+13 to -13) This feature was omitted from 99/4A floating point, but I find satisfaction that the Radix 100 designer originally make good use of all the bits.


990 TI BASIC used Radix 100 format for REAL and DECIMAL, not the the-standard IBM format used on the 990 elsewhere.

 

  • Thanks 1
Link to comment
Share on other sites

On 9/26/2019 at 8:22 PM, HOME AUTOMATION said:

With regard to print loop time testing... It has been my experience that many  of the earier 99/4As... have an error in the garbage collection routine, that exacts a whopping nearly 2 sec. penalty every time it executes... this becomes more frequent as free space diminishes... I believe this occurs even when mearly printing string or numeric constants. My old TI BASIC programing(long lost) made rather heavy use of DEFs that included... ASC, CHR$, VAL and other functions. The program was often using as much memory as TI BASIC would allow. The lock-ups would occur less than ten seconds apart, nearly paralysing my program completely. My understanding is that this routine has been changed, perhaps more than once, finally being completely corrected. I'm  not sure how emulators dealt with this. But this could account for vastly different "loop/time" results.
Recently I had seen a fully commented source listing of the GPL responsible, including the names of the programmers and dates of corrections. Can't seem to locate it now though.

rediscovered...

 

1392617051_garbagecollect1.thumb.JPG.2f3b37c4cc6fd327c554fe3b5e946b5d.JPG

1738785834_garbagecollect2.thumb.JPG.b2f0d7556f4265b568dc162232763eea.JPG

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

On 9/28/2019 at 9:17 PM, senior_falcon said:

Compiled BASIC, Forth, GPL are all threaded code which run pretty fast but nothing like assembly.

 

I think forth and compiled basic run at similar speeds. 

I had to jump in. :)

 

Are we sure the Compiled BASIC is threaded? (I have never looked into the internals.)

 

Current versions of Forth for TI-99 are threaded yes, but modern Forth systems generate native code.

(I have the beginnings of a Native code Forth compiler for TI-99 that can compile simple programs)

 

If we do a line by line translation of a compiled BASIC program to Forth then speeds are similar.  I did a sieve of Eratosthenes that was slightly faster in CAMEL99 Forth than compiled BASIC, but then I could compile it as Direct threaded Forth and it is 15% faster.  I did not explore all the optimization possibilities.

 

The opportunities for optimization in Forth are large depending on the programmer's knowledge:

  • Use text macros that remove sub-routine calls at compile time for inner loop routines
  • replacing  critical snippets of code with the Assembly language equivalent is so easy you don't even hesitate to do it when needed
  • Write macros in Assembly with Forth word names so that you can write Assembly language that looks like Forth
  • Steal machine code from the kernel and run those routines inline (no interpereter between each one) (2X speed up)

And the number one way to speed up code...  Do it differently!  Better Algorithms beat better compilers every time.

 

And because Forth, like BASIC, has an interpreter you can experiment and iterate quickly to find better methods.

(Even the Forth Assembler is interactive)

 

</Zealot hat> ?

 

 

 

 

 

 

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

"In computer science, the term threaded code refers to a programming technique where the code has a form that essentially consists entirely of calls to subroutines. It is often, but not only, found in compiler implementations that generate code in that form and/or are implemented in that form themselves. The code may be processed by an interpreter, or may simply be a sequence of machine code call instructions. "

 

The XB compiler does not generate assembly code. Instead, it converts the BASIC program into DATA statements. For example:

10 CALL HCHAR(ROW,COL,42,32)

20 CALL VCHAR(ROW,COL,65,24)

compiles to:

L10 DATA HCHAR,NV1,NV2,NC1,NC2

L20 DATA VCHAR,NV1,NV2,NC3,NC4

When running, the interpreter retrieves the address of HCHAR, goes there, then retrieves the variables and constants and puts them on the screen. The pointer then advances to the next data statement, retrieves  VCHAR, goes there, retrieves the 4 variables and puts them on the screen.  And so on.

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

8 hours ago, apersson850 said:

Yes, this feature comes from the TI 990. So it's not unique. I was rather referring to that in computers at the same ambition level as the TI 99/4A, it's rare.

You made a good point, that other home computers didn't add subprograms to Basic this smartly. I only know Apple II, but accessing cards from Applesoft Basic was a mess.

 

It's still pretty amazing that we can still put modern hardware on a card, put a DSR on it, and have some CALLs use it from BASIC. (CALL TIPI (: )

 

 

 

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

21 hours ago, FarmerPotato said:

 

 

All about CALLs in 990 TI BASIC

The CALL syntax, in 99/4A BASIC and Extended Basic, matches the syntax used in TI BASIC for the 990 minicomputer.  So TI BASIC was designed for named subprograms well before the 99/4A. 

 

It's clear to me that the 99/4A TI BASIC and Extended BASIC were a deliberate subset of 990 TI BASIC with few differences. While reading about the CALL syntax, I also read that 990 TI BASIC used RADIX 100 (with an important feature for DECIMAL type.)


I played with 990 TI BASIC yesterday on Dave Pitt's excellent 990 simulator with DNOS. Basic is already installed. However, it is not clock-speed accurate (it runs fast) so timing BASIC benchmarks is silly. https://www.cozx.com/dpitts/ti990.html


 

In the TI BASIC Reference Manual, 1-Dec-83:  http://www.bitsavers.org/pdf/ti/990/basic/


Page 9-3 describes the DEF statements, which may have a return type, or be multi-line.

Page 9-5 describes the CALL/SUB/SUBEND statements.

Page 11-6 describes how to CALL assembly language routines from 990 TI BASIC, and explains the Radix 100 format of parameters.

 

The CALL/SUB statements, which may have variable types declared:

 


SUB HSTEP(REAL A, INTEGER B, REAL C)
IF A=0 THEN SUBEXIT
C = A * 2^(B/12)
SUBEND

REAL X = 220
INTEGER N = 5
REAL Y
CALL HSTEP(X, N, Y)

An optional type after SUB can set one type for all parameters.

 

ESUB is used instead of SUB to write subroutines that have external visibility. The ESUBs are callable from other programs.


Page 9-3 describes the DEF statements, which may have types or be multi-line:


DEF AVG(X,Y) = (X+Y)/2
DEF REAL PI = 3.1415926535

X = AVG(A,B)/PI

or

DEF XYZ(A,B,C)
XYZ = A + B + 2
FNEND


One of TI's examples of a multi-line DEF is the square root algorithm (also explained to students in TI Learning Center's DC AND BASIC ELECTRICITY textbook.)

 

CALL assembly


Section 11-6 describes how to add assembly language routines to 990 TI BASIC and explains the Radix 100 format.

 

Calling assembly routines is not like  99/4A TI BASIC:

 


LIBRARY "*pathname"
CALL ".ASMBLY"(A$, A, B, C)

where pathname is your assembled and linked code, for example .BSCSUP. The * indicates that the routine should persist in memory.  

 

The first two words of the file are a BLWP vector; BASIC overwrites the workspace pointer at load time.  Assembly subroutines return with RTWP. Important assembly libraries distributed with TI BASIC were the .SORT library and keyed file database.

 

BASIC parameters are passed to the assembly routine in a 18-word block of memory:

 

Continuing the example:

 


REAL A
INTEGER B,C
CALL ".ASMBLY"(A$, A, B, C)

WP-36 Number of parameters
WP-34 2 bits for each parameter type: 
00 end of list
01 integer
10 real or decimal
11 string
WP-30 pointers ...

For the example above,

 


>0004
>E500  * b'11100101 00000000 codes for string, real, int, int
>0000
ptr to A$
ptr to A
ptr to B
ptr to C
>0000
...

Figure 11-1 goes on to unpack the variable formats in memory. In particular, it describes RADIX-100 format for REAL. Integers are 16 bits.

 

REALs are stored in the quite familiar 99/4A format. As we know, the mantissa bytes range from 0-99, wasting a bit per byte (1.3 bits to be pedantic). TI BASIC represents type DECIMAL by using 6 leftover bits to store the number of significant decimal places! (+13 to -13) This feature was omitted from 99/4A floating point, but I find satisfaction that the Radix 100 designer originally make good use of all the bits.


990 TI BASIC used Radix 100 format for REAL and DECIMAL, not the the-standard IBM format used on the 990 elsewhere.

 

 

Thank you. This man knows what he is talking about. ?

Sure you dont wanna help Rich and become famous? ;-)

Link to comment
Share on other sites

On 9/28/2019 at 5:39 PM, RXB said:

Sadly yes that is the end result.

All TI Basic or XB programs would have to be converted each time or suffer even worse performance issues.

As this new TI Basic or XB would have so much added to interpreter to look for if a number is Integer or Floating Point.

This would force a Compiled version to not slow down the programs, thus defeating the entire reason for Basic in the first place.

This is what also happened to all Compiled Basic versions, as if you compiled Basic, just might as well just jump to C or Pascal or Assembly.

 

How about adding two NEW datatypes XBINTEGER and XBFLOAT to RXB? Extended Basic is an extension of TI-Basic! Now old programs could use the old stuff, and new programs could use these two new datatypes ? This would result in NO compatibilityproblems with old Basicprograms.

  • Like 1
Link to comment
Share on other sites

4 hours ago, Sid1968 said:

 

How about adding two NEW datatypes XBINTEGER and XBFLOAT to RXB? Extended Basic is an extension of TI-Basic! Now old programs could use the old stuff, and new programs could use these two new datatypes ? This would result in NO compatibilityproblems with old Basicprograms.

I like that idea. The less i need to boot into stock Basic or TI-XB, the better.

  • Thanks 1
Link to comment
Share on other sites

12 hours ago, senior_falcon said:

"In computer science, the term threaded code refers to a programming technique where the code has a form that essentially consists entirely of calls to subroutines. It is often, but not only, found in compiler implementations that generate code in that form and/or are implemented in that form themselves. The code may be processed by an interpreter, or may simply be a sequence of machine code call instructions. "

 

The XB compiler does not generate assembly code. Instead, it converts the BASIC program into DATA statements. For example:

10 CALL HCHAR(ROW,COL,42,32)

20 CALL VCHAR(ROW,COL,65,24)

compiles to:

L10 DATA HCHAR,NV1,NV2,NC1,NC2

L20 DATA VCHAR,NV1,NV2,NC3,NC4

When running, the interpreter retrieves the address of HCHAR, goes there, then retrieves the variables and constants and puts them on the screen. The pointer then advances to the next data statement, retrieves  VCHAR, goes there, retrieves the 4 variables and puts them on the screen.  And so on.

 

This looks very much like compiled, high-level Forth code. Here is the Forth code for QUERY :

: QUERY   ( --- )
   TIB @ 80 EXPECT      ( get up to 80 characters in the terminal input buffer)
   0 IN !  ;            ( reset TIB cursor to start of buffer)

 

And here is how it is compiled into the dictionary starting with the code field of QUERY :

QUERY  DATA DOCOL
       DATA TIB,AT,LIT,>50,EXPECT,ZERO,IN
       DATA STORE,SEMIS

 

...lee

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

On 9/28/2019 at 10:06 AM, adamantyr said:

If I remember right, the BASIC interpreter uses a full 8 bytes for every numeric variable but it does treat integers slightly differently, only using 2 bytes for them. If you ever interacted that variable with decimals though it became a float from then on.

 

An interesting early case of a weakly cast variable type.

 

To answer your earlier question, adding an Integer type explicitly is a lot of headache. If you use the % as an indicator it could break old BASIC programs using it in a variable name. Most functions would need to be altered to accept integer or numeric. You would need byte, word and double word versions. Conversion functions would need to be added. And finally, what exactly are you gaining? Memory mostly, but not a lot. It only makes sense if you are designing a new BASIC with 0% compatibility.

 

Where can you see BASIC treating integers this way?

 

In 99/4A console TI BASIC:

 

When I look in VDP (around >3700) at the stored statement CALL HCHAR(1,1,42,768) I see the numbers stored as strings in the program. 

The statement A=1234.3333 stores the number as a string in the program.

 

When I assign an integer to a variable see 8 bytes of stack written with the values

A = 1 gives 40 01 00 00 00 00 00 00 
A = 1.5 gives 40 01 32 00 00 00 00 00
A = 16 gives 40 10 00 00 00 00 00 00
A = 64 gives 40 40 00 00 00 00 00 00
A = 99 gives 40 63 00 00 00 00 00 00
A = 100 gives 41 01 00 00 00 00 00 00
A = 10000 gives 42 01 00 00 00 00 00 00
A  = -1 gives BF FF 00 00 00 00 00 00
A = -99 gives BF 9D 00 00 00 00 00 00

 

These are Radix 100 floating point values. It happens that small integers from -99 to 99 are easy to convert out of Radix 100 without any multiplication.

 

Why add integer types?

 

I agree that adding an integer type is a big deal, because of all the argument checking code in built-in functions.

 

Some gains to be had are:

  • avoiding costly CFI and CIF conversion routines,
  • avoiding costly string-to-number conversion,
  • fast numeric calculations where only integers are required, such as indexing through array indices, some equations in integer only.

It has been done before in 990 TI BASIC, so we can try it. 

 

In TI BASIC for the 990/4, the operating system and basic interpreter take up a little more than 32K, leaving 29K for the BASIC program.

It provides INT, REAL, and DECIMAL type declarations.

 

Integers are declared like so:

20 INTEGER A
30 A = 5

 

or for an array,

20 INTEGER A(10)


REAL variables consume 8 bytes of stack space, INTEGER 2.

Between REAL X(10) and REAL X(11) there is 8 bytes difference. For INTEGER it is 2 bytes.

 

Because it is a superset of 99/4A TI BASIC, you could type in any program and run it with good compatibility - all variables would default to REAL. It doesn't have HCHAR for one, and such subroutines would have to marshal their (integer desired) arguments by checking the input type. (If you wrote SUB HCHAR you could test the effect of changing parameter types from INTEGER to REAL.) Still, HCHAR could be written to work much faster if it didn't have to do any conversions from floating point to an integer VDP address.

 

I did one experiment - this is in sim990 on my fast PC, so times are only relative.

100 N=10000
110 REAL A
120 FOR I=1 TO N
130 A=A+1
140 NEXT I
150 PRINT A

time = 5 seconds

80 INTEGER N
90 INTEGER I
110 INTEGER A

time = <3 seconds

Not sure if that constant 1 should be treated somehow

 

Simple multiplication seems to go twice as fast:

 

100 N=10000
110 REAL A
120 A=1
130 FOR I=1 TO N
140 A=A*1.01
150 NEXT I
160 PRINT A

6 seconds

70 INTEGER B
80 INTEGER N
90 INTEGER I
110 INTEGER A
140 B=A*2

3 seconds

 

I hope this illustrates that there is a large gain to be had from a BASIC with integer types.

 

  • Like 1
  • Thanks 1
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...