Notes on Assembly Language Routines within BBC BASIC

Having identified which routine is critical to performance, it's highly advisable to convert any variables used by the Assembly Language facility to fixed format areas of memory, RESERVED by a BASIC DIM statement.

Mistakes in Assembly Language are usually fatal, causing a crash. Therefore, you need to be careful that the variables reserved are in precisely the right format expected by the Assembly Language command (opcode). Floating Point opcodes usually expect a 64-bit variable (which is automatically converted to 80-bit).

Be careful not to inadvertantly leave data on the Floating Point Stack when exiting the Assembly Language routine.

Get an algorithm to work perfectly in BASIC first, before coding the same routine in Assembly Language.

One advantage of Assembly Language routines embedded within a BASIC program is that usually the variables have been "conditioned", in that they lie in a certain range, before being presented to the Assembly Language routine. The output is usually therefore confined to a certain range of values, and so there is often less need for general-purpose exception or error handling. That's one big reason why the Assembly Language routine is quicker; it's low on error-checking overheads.

If you're writing code using Floating Point Opcodes make sure to include the statement *FLOAT64 at the start of your BASIC program - or the FP instructions will NOT WORK, and BASIC will crash.

For a very basic "noddy" illustration of the use of the most commonly needed non-Floating Point Assembly instructions, you may like to try this listing of mine, which adds numbers together and a couple of other things: FirstAssembly

I have now added THREE versions of a basic illustration of the use of FLOATING POINT Assembly instructions.

FirstFPv1 FirstFPv2 FirstFPv3

Advanced Mathematical Routines in Assembly Language

Normal is a demo of how to transfer a fairly complex calculation from BB4W into ASM, using the Normal Distribution as the example. The Normal Distribution involves estimating the value of an integral, which cannot be performed analytically anyway. That means it's a numerical integration according to the formula shown at the bottom of the page, where mu is the mean and sigma is the standard deviation. Since the integral is essentially zero below a lower integration limit of -6.0 (and is almost static at 1 above an upper limit of 6.0), I approximate the integral with a finite sum starting at the lower limit of -6.0

The approximation is easy in BASIC; I just add up a lot of numbers of the type EXP(X). It's not so easy in Assembler - since there is NO straightforward EXP function. To achieve EXP(X) in Assembler, you have to do the following rather perverse looking calculation;

1) Notice that EXP(X) = 2^{X.log2(e)} and that there is the Floating Point (FP) instruction FLDL2E which pushes "LOG-TO-BASE-TWO-OF-e" onto the FP stack.

2) Notice that the FP instruction to perform 2^X ONLY WORKS if X lies between -1 and +1, so notice that 2^X=2^(K+Y) where K is an integer, and Y is between -1 and +1.

3) Work out 2^K using integer arithmetic (easy using the shift-left or shift-right instructions), and work out 2^Y using the FP instruction F2XM1 which calculates 2^number - 1. (No, I have no idea why it does this. It just does!) Then you add 1 to get 2^Y.

4) Finally, multiply together 2^K and 2^Y, and that will be EXP(X), as required.

Return to Top Page

Next Page