BBC Micro Elite

```Doing basic arithmetic with sign-magnitude numbers

Elite uses a lot of sign-magnitude numbers, where the sign bit is stored
separately from an unsigned magnitude. The classic examples are the ship
coordinates at INWK, which are stored in 24 bits as as (x_sign x_hi x_lo),
where bit 7 of x_sign is the sign, and (x_hi x_lo) is the coordinate value.

This means that when we come to do arithmetic on sign-magnitude numbers, we
have to write our own routines for everything from addition and subtraction
to multiplication and division, as the standard two's complement maths that
the 6502 supports won't work.

For example, let's try adding 127 and -1 as sign-magnitude numbers, first
using sign-magnitude arithmetic. 127 is 01111111 as a sign-magnitude number,
while -1  is 10000001, and:

127 + -1 = 0 1111111 + 1 0000001
= 0 1111111 - 0 0000001
= 0 1111110
= 126

However, if we use the built-in ADC instruction, we get the following:

127 + -1 = 01111111 + 10000001
= 00000000

which is a completely different result.

algorithm. We want to add A and S, so:

* If both A and S are positive, just add them as normal

* If both A and S are negative, then add them and make sure the result is
negative

* If A and S have different signs, then we can use the absolute values of A
and S to work out the sum, as follows:

* Subtract the smaller absolute value from the larger absolute value

* Give the answer the same sign as the argument with the larger absolute
value

To see why this works, try visualising a number line containing the two
numbers A and S, with one to the left of zero and one to the right. Adding
the numbers is a bit like moving the number with the larger absolute value
towards zero on the number line, moving it by the amount of the smaller
absolute number; so it's like subtracting the smaller absolute value from the
larger one. You can also see that the sum of the two numbers will be on the
same side of zero as the number that is furthest from zero, so that's why the
answer should have the same sign as the argument with the larger absolute
value.

We can implement these steps like this:

* If |A| = |S|, then the result is 0

* If |A| > |S|, then the result is |A| - |S|, with the sign set to the same
sign as A

* If |S| > |A|, then the result is |S| - |A|, with the sign set to the same
sign as S

So that's what we do in the ADD routine to implement 16-bit sign-magnitude
addition. The same basic approach can be found in lots of Elite's arithmetic
routines: check the signs of the two operands, then add, subtract, divide or
multiply as appropriate, and finally set the sign bit correctly.

```