6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 8:22 am

All times are UTC




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: [OT] BBC Basic
PostPosted: Mon Aug 10, 2020 5:42 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
Recently, Garth asked:

Quote:
I have never seen a BBC Micro, but I hear nothing but good about its BASIC.


A while back Ed gave a good description of the old Beeb; http://forum.6502.org/viewtopic.php?f=3&t=3482&p=40799&hilit=bbc+micro#p40799 so no point repeating it really, but a picture:

Attachment:
BBCMicro.jpg
BBCMicro.jpg [ 282.39 KiB | Viewed 15734 times ]


They keyboard layout is a little unusual by todays standards, but in 1981 everyone was still making it up as they went.. One thing Ed didn't mention in his good write-up was the arrow keys and the copy button - essentially, you used the arrow keys to move a 2nd cursor round the screen, then they copy key would copy the character under the cursor into they keyboard input buffer, so more like the Apple II (Esc commands, then forward arrow) than the Commodore PET, etc. style of editing. It worked well enough.

There were a few variants - a cut-down version called the Electron and ending with the BBC Master which had 128KB of RAM and space for an internal 2md processor as well as an external one. (Note the fore-runner to the BBC Micro was called the Acorn Atom and the working name for the BBC Micro was the Proton before it took on the name of the BBC Micro)

As for the BASIC:

I think it's fair to say that the boffins at Acorn HQ had a good, solid comp-sci background and having seen the 6502 "competition" (ie. the various MS Basics for the most part), so with 16MB of ROM space and a built-in operating system (another 12KB) they made a good job.

Integers are 32-bit and pure integer expressions are evaluated as integers without a conversion to floating point. Floating point numbers are 40-bits wide and highly optimised. To the point that my 'benchmark' text-mode Mandelbrot (using floating point only) is a shade under twice the speed in BBC Basic than a MS Basic for the same clock speed.

There are no peek/poke commands as such, however you can store data in RAM and read it from RAM using byte and word indirection operators. To read a byte at location $42 (Acorn use & for hox. notation in BBC Basic, so &42)

Code:
var = ?&42


var here would be floating point, the usual % suffix to indicate integers, so var%.

To read a word (4 bytes), you would use the ! operator (often called 'pling' although I never got past calling it an 'eek' mark)

These can work with an offset, so
Code:
var% = X%?4
would fetch the byte in memory location addressed by X% plus 4. Assignment is: X%!4 = var%[/code]

The question now is how to allocate RAM for poking your data into and the DIM statement allows you to use the DIM'd variable as an address in the indirection operators

Code:
  DIM C% 100
  C%!4 = &123456AB


Single letter integer variables from @% through Z% are stored in fixed memory locations, so are extra fast.

Variables can be any number of characters long and all characters are significant. Upper and lower case are distinct.

Loops - the usual FOR loop, but also REPEAT .... UNTIL condition (spread over multiple lines)


Functions and Procedures are named and can be written over multiple lines. They can take parameters, can have have local variables and be called recursively.

A recursive string reversal example:

Code:
  100 PRINT FN_REV ("Gordon Henderson")
  110 END
  120 DEF FN_REV(S$)
  130 IF LEN(S$) = 1 THEN =S$
  140 =RIGHT$(S$,1) + FN_REV(LEFT$(S$,LEN(S$)-1))


Note that I used an underscore character to start the name - one quirk is that there can't be a space between the function name and the DEF FN instruction. Not everyone did it that way though, some used lower case and some just got on with capitals...

There is also a built-in 2-pass assembler... However you have to manage the 2 passes yourself using a FOR loop. Here is an example from the book:

Code:
 10 REM DOUBLE HEIGHT IN TELETEXT
 20 WIDTH 36: MODE 7
 30 VDU 28,0,23,39,0
 40 write=!&20E AND &FFFF
 50 DIM PROG 100
 60 FOR PASS = 0 TO 1
 70 P%= PROG
 80 [
 90 OPT PASS*3
100 CMP#&D : BNE noter
110 PHA :JSR write
120 LDA#&8D : JSR write
140 LDA#&08 : JSR write
150 LDA#&8D : JSR write
160 PLA : RTS
170 .noter CMP #&20 : BCS legal
180 JMP write
190 .legal PHA : JSR write
200 LDA #$0B : JSR write
210 LDA #&08 : JSR write
220 PLA : PHA : JSR write
230 LDA #&0A : JSR write
240 PLA : RTS
250 ]
260 NEXT PASS
270 !&20E=!&20E AND &FFFF0000 OR PROG
280 END


Without going into what that's doing in too much depth, the FOR loop is the 2 passes and the OPT instruction signals the assembler what to do - so OPT 0 on the first pass and OPT 3 on the 2nd pass (OPT 0 means ignore errors, needed as we don't have the forward references at that point, and OPT 3 means report the errors) P% tells the assembler where to put the assembled code, so the code is stored in the array created in the DIM PROG instruction. Assembly code is placed inside the [ ] section. Note labels starting with a dot and multiple assembly statement per line using the colon. Macros, while not part of the assembler can be trivial added with procedures - it's still interpreting BASIC as well as running the assembler, so you can make it call a procedure to output more code.

That's mostly the main differences from a 'classic' MS style Basic. The Operating System specific stuff relates mostly the the graphics and sound, but there was on-board analog input (for joysticks, etc.) the OS provided hooks to the filing systems (tape, disk, network) and most other IO - You were not supposed to poke the screen memory, but use the built in's instead - and if you obeyed the rules then your code would work in a 2nd processor (initially a 3Mhz 6502 with much more RAM) without change. (The latest 2nd processor is an ARM based one that will give you a ~300Mhz emulated 6502...)

(And speaking of the ARM, the BBC Micro was used to help develop and test the ISA and the first ARM processor was implemented as a 2nd processor to a BBC Micro - the A in ARM is Acorn)

The key thing is that the BASIC itself is de-coupled from the underlying operating system. The OS manages the screen, keyboard, hardware, etc. leaving the language ROM (Basic in this case) to do what it does best - this enabled development of many other language ROMs (Forth, Comal, Pascal, Lisp, Logo, etc.) leaving more space for the language to do its thing with the OS providing a common interface). Note also - A language ROM could be wordprocessor, spreadsheet, database and so on. The ROMs all occupied the same physical space: &8000 through &BFFF with the OS providing the means to switch between them. (The ROMs were also filing systems and other utilities like graphics extensions and again the OS managed this transparently to the application, so a BASIC program could open a file and it didn't need to know if the file was stored on tape, local disk or network disk.

As for BBC Basic being used in a home-brew system... It's possible and I've done it, although it did require me to write my own version of the Acorn MOS (Machine Operating System) to support the system calls that BASIC needs (the up-shot of this is that I'm able to run some other BBC ROMs too). The OS interface is very well documented and dis-assembled and back-annotated.

The original sources appear to have been lost, along with the copyright holder(s). There is a somewhat convoluted trace of ownership that (as far as I know) ended with a US bank which was destroyed in the twin towers disaster. Does that mean you can use it in a commercial project? Who knows. I'd not like to say, but to my knowledge, no-one has reared their head up to claim copyright.

Note that there are other BBC Basics - The most notable one is RT Russels BBC Basic for Windows. I think RTR wrote the original BBC Basic port to the Z80 2nd processor (which ran CP/M) then went on to develop a commercial version to run under Windows. Today, it's been open sourced and runs under Linux platforms including the Raspberry Pi.

I did a demo of BBC Basic vs. MS. Basic (Actually EhBASIC) on my Ruby board some time back - originally to demonstrate it to some of the Commander X16 people but they go all huffy and pulled it from their facebook pages, however it's on youtube channel here: https://www.youtube.com/watch?v=ci_70naIg_Q and has the Mandelbrot demo timed.

Hope this helps explain it a little.

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Mon Aug 10, 2020 6:32 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Very nice and detailed - thanks for writing it up!

One possibly notable extra thing: there are integer, float, and string variables, but also the single-letter integer variables have special handling which makes them extra fast. The operators AND OR and NOT work bitwise on integer variables and at the same time have their usual boolean meaning.

Perhaps also the file handling keywords are notable? OPENIN, OPENUP, OPENOUT, CLOSE#, PTR#, EXT#, EOF#, PRINT#, INPUT#, BGET#, BPUT# for sequential and random access. The filing system itself is abstracted and implemented in a separate ROM: cassette, floppy, hard disk, network.

Also arguably notable: Richard wrote BBC Basics for a number of Z80 systems, including Sinclair's Z88 and Amstrad NC100. His latest versions are multi-platform, free, and open source. Each one has an assembler suited to the host CPU: x86, ARM.

Many of the various second processors also had ports of BBC Basic: 32016 and ARM were both 32 bit CPUs running BBC Basic, in the 80s.


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Wed Aug 19, 2020 7:24 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
drogon wrote:
A recursive string reversal example:
Code:
  100 PRINT FN_REV ("Gordon Henderson")
  110 END
  120 DEF FN_REV(S$)
  130 IF LEN(S$) = 1 THEN =S$
  140 =RIGHT$(S$,1) + FN_REV(LEFT$(S$,LEN(S$)-1))

I take it the `=` without an expression in front of it is the return statement?

This is pretty nice, and fairly easy to read (for BASIC). Was recursion often used in this way? Did BBC BASIC have tail call optimization?

Quote:
There is also a built-in 2-pass assembler... However you have to manage the 2 passes yourself using a FOR loop.

Ah! So that explains those loops. I always wondered about that. Had any of the code I'd seen before used PASS as the loop variable, I might have clued in earlier, but as it stands it's just quite mysterious to those not in the know.

Quote:
The [language] ROMs all occupied the same physical space: &8000 through &BFFF with the OS providing the means to switch between them. (The ROMs were also filing systems and other utilities like graphics extensions and again the OS managed this transparently to the application, so a BASIC program could open a file and it didn't need to know if the file was stored on tape, local disk or network disk.

This general idea was actually also eventually brought into Microsoft BASIC with the MSX BIOS and BASIC. Probably not as cleanly, though.

Quote:
Hope this helps explain it a little.

Yes, this was quite an informative post. Thanks!

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Wed Aug 19, 2020 8:44 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
cjs wrote:
drogon wrote:
A recursive string reversal example:
Code:
  100 PRINT FN_REV ("Gordon Henderson")
  110 END
  120 DEF FN_REV(S$)
  130 IF LEN(S$) = 1 THEN =S$
  140 =RIGHT$(S$,1) + FN_REV(LEFT$(S$,LEN(S$)-1))

I take it the `=` without an expression in front of it is the return statement?


Yes. In much the same way in an MS Basic has the single-line:
Code:
 DEF FNR(D) = D * 3.14 /180
sort of thing.

cjs wrote:
This is pretty nice, and fairly easy to read (for BASIC). Was recursion often used in this way? Did BBC BASIC have tail call optimization?


I've no idea just how many people used it - I suspect maybe those with a more computery background than the typical home user. I was taught BASIC at secondary school by an Algol programmer so had "structure" and extra goodness thrown at me from the start, (even though the local 'mainframe' and Apple BASICs didn't support those constructs), but others may not have been that lucky... I doubt there's much optimisation though.

cjs wrote:
Quote:
There is also a built-in 2-pass assembler... However you have to manage the 2 passes yourself using a FOR loop.

Ah! So that explains those loops. I always wondered about that. Had any of the code I'd seen before used PASS as the loop variable, I might have clued in earlier, but as it stands it's just quite mysterious to those not in the know.


Yes, it was a bit obscure, but it was used a lot - especially by games writers and so on with clever ways to manage code position, relocation, using BASIC procedures as macros and so on.

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Wed Aug 19, 2020 9:41 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8544
Location: Southern California
drogon wrote:
A recursive string reversal example:

In the BASIC that's on my HP-71, I would just do REV$(<insert_string_expression_here). No program necessary. :mrgreen:

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Thu Aug 20, 2020 10:16 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
drogon wrote:
I doubt there's much optimisation though.

Well, tail call optimization (TCO) is not a speed optimization that you could have more or less of: it determines what you can and cannot do with recursion. (Remember, recursion is both conceptually simpler* and more powerful than the less generic looping constructs such as DO, FOR and WHILE used in many popular languages. But mathematical beauty isn't generally admired too much when implementation details mean things can't actually run as they need to.)

TCO determines whether or not the system continues to store unneeded call frame data when making a call to another function as the last call ("tail position") of a function, which marks a point at which that call frame data will never be used again. An example would be something along the lines of

Code:
100 DEF FN_MAIN()
110 C$ = FN_GET_COMMAND()
120 IF C$ = "QUIT" THEN =0
130 FN_DO_COMMAND(C$)
140 =FN_MAIN()

Without TCO, run that for long enough and it will explode, as it has filled up memory with all the old versions of C$ that it doesn't need and will never use again.

TCO is a very common technique in assembly language; whenever you replace JSR PRINT; RTS with JMP PRINT you're doing TCO.

Quote:
Yes, it was a bit obscure, but it was used a lot - especially by games writers and so on with clever ways to manage code position, relocation, using BASIC procedures as macros and so on.

Well, by "obscure" I just meant the particulars of managing the two-pass thing. In-line assembler doesn't strike me as particularly obscure, and has been a useful feature in programming languages since at least LISP 1.5.

----------
* Conceptually simpler for those coming to programming de novo or who understand both recursion and the other constructs. Of course people who initially learned the idioms of looping constructs often end up in a position where recursion seems harder to understand because of the specific knowledge and practice that they already have.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Thu Aug 20, 2020 11:28 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
I had a quick check, and it doesn't look like BBC Basic optimises tail calls in functions. I suppose one could add this feature to a wishlist for enhanced Basics...


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Wed Sep 09, 2020 9:22 pm 
Offline

Joined: Sun Feb 22, 2004 9:01 pm
Posts: 109
drogon wrote:
The keyboard layout is a little unusual by todays standards, but in 1981 everyone was still making it up as they went.
Well, actually not. The BBC used the then-long-standing EMCA 'bitpaired' layout, where symbols are the main keys EOR 16,
as god intended. The 'bitmap' layout lives on today in the standard Japanese keyboard layout.

Quote:
Note that there are other BBC Basics - The most notable one is RT Russels BBC Basic for Windows.
(plug)PDP11 BBC BASIC(plug) :D

_________________
--
JGH - http://mdfs.net


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Wed Sep 09, 2020 9:24 pm 
Offline

Joined: Sun Feb 22, 2004 9:01 pm
Posts: 109
BigEd wrote:
I had a quick check, and it doesn't look like BBC BASIC optimises tail calls in functions. I suppose one could add this feature to a wishlist for enhanced BASICs...

That's something the /programmer/ would do, not the language.

_________________
--
JGH - http://mdfs.net


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Sat Sep 12, 2020 6:25 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I've been playing around with sorting algorithms, and my current approach to quicksort is to put open partitions into a priority queue (smallest first) instead of directly recursing into them. The code actually works out simpler once you have more than one pivot, compared to manually choosing the order to do the recursion just to enable tail-recursion, and O(log n) space complexity is guaranteed.

So I now have a septenary quicksort (three pivots, three partitions equal to the pivots, plus four open partitions divided by them) which turns out to be quite efficient, even though I haven't finished tweaking the partitioning routine. And then there's the septenary stable quicksort which outperforms many in-place mergesorts on at least modest-sized problems. Ah, good times.

Structured data is one of the big missing features from BBC BASIC. Not only data objects with a variety of named members, but things like growable arrays, priority queues, associative arrays, and so on. Tricky to squeeze those into a 16KB ROM, but it's something to consider for an '816 focused version.


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Fri Sep 25, 2020 6:57 pm 
Offline

Joined: Sun Feb 22, 2004 9:01 pm
Posts: 109
Chromatix wrote:
Structured data is one of the big missing features from BBC BASIC. Not only data objects with a variety of named members, but things like growable arrays, priority queues, associative arrays, and so on. Tricky to squeeze those into a 16KB ROM, but it's something to consider for an '816 focused version.

...and exists in the Windows and SDL versions.

_________________
--
JGH - http://mdfs.net


Top
 Profile  
Reply with quote  
 Post subject: Re: [OT] BBC Basic
PostPosted: Tue Sep 13, 2022 5:37 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
I rediscovered this thread a few weeks ago, as I'd started to think there needed to be one. It's good to see that it highlights pretty much the things I would have done... except one!

The provision of ~ and & for hex output and input, respectively, are very convenient, and also in my view really help in that transition from the Basic machine to the machine code machine. Obscure addresses or values in decimal are often more meaningful and more decodable in hex.

Although, as noted, BBC Basic gives facilities to allocate memory and to read and write it, both by byte and by word, only in very rare circumstances is it necessary to peek or poke locations to get the feature or function you want: it has words for sound and graphics and keyboard actions, and even for reading ADC values. Again, it's less obscure and arbitrary than it might have been.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 40 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron