Aviator on the BBC Micro

```       Name: Add16x16Bit0                                            [Show more]
Type: Subroutine
Category: Maths
Summary: Add two 16-bit numbers that have their signs in bit 0
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:

This routine adds two 16-bit numbers, both of which have their signs in bit 0
of the low byte. It calculates:

(S R) = (H G) + (J I)

The result in (S R) has the sign in bit 0 of the low byte.

Arguments:

(H G)                A signed 16-bit number, with the sign in bit 0 of G

(J I)                A signed 16-bit number, with the sign in bit 0 of I

Returns:

(S R)                The result of the multiplication, with the sign in bit 0
of R

K                    The sign of the result (in bit 0)

LDA G                  \ Set K to the sign of G (from bit 0)
AND #1
STA K

EOR I                  \ If G and I have different sign bits, then this will
AND #1                 \ set A to 1, in which case jump to abit2
BNE abit2

\ If we get here then the two arguments (H G) and (J I)
\ have the same sign, which is stored in K

LDA G                  \ Set (S R) = (H G) + (J I)
CLC                    \
ADC I                  \ starting with the low bytes, setting bit 0 of the
ORA K                  \ numbers with sign K will have sign K)
STA R

LDA H                  \ Then adding the high bytes
STA S

\ return from the subroutine, as the result is correct

LDA #%11111111         \ The addition overflowed, so we return the maximum
STA S                  \ value in (R S), which has every bit set except for the
LDA #%11111110         \ sign bit, which is set to K
ORA K
STA R

.abit1

RTS                    \ Return from the subroutine

.abit2

\ If we get here then the two arguments (H G) and (J I)
\ have different signs, with the sign of (H G) stored in
\ K

LDA G                  \ Set (S R) = (H G) - (J I)
SEC                    \
SBC I                  \ starting with the low bytes
STA R

LDA H                  \ And then the high bytes
SBC J
STA S

\ Otherwise the result is correct apart from the sign,
\ and the sign of the result should be that of (H G), as
\ (H G) is the larger value (i.e. it has the highest
\ magnitude), as otherwise the subtraction would
\ underflow

LDA R                  \ Set the sign bit of (S R) to K, as that contains the
AND #%11111110         \ sign of (H G)
ORA K
STA R

RTS                    \ Return from the subroutine

.abit3

\ If we get here then the (H G) - (J I) subtraction
\ underflowed, so (J I) is the larger value (i.e. it has
\ the highest magnitude)
\
\ We therefore need to negate the subtraction result to
\ get (J I) - (H G), and the sign of the final result
\ should be given the sign of (J I), as that's the
\ dominant part... and as K contains the sign of (H G)
\ and we know (H G) and (J I) have opposite signs, we
\ should therefore give the result the opposite sign to

LDA #0                 \ Negate the (S R) to get the correct result,
SEC                    \
SBC R                  \   (S R) = 0 - (S R)
AND #%11111110         \
ORA K                  \ while also setting the sign in bit 0 to the opposite
EOR #1                 \ of K
STA R
LDA #0
SBC S
STA S

RTS                    \ Return from the subroutine
```