Skip to navigation

Aviator on the BBC Micro

Maths: Multiply8x16

Name: Multiply8x16 [Show more] Type: Subroutine Category: Maths Summary: Multiply an 8-bit and a 16-bit number Deep dive: Times tables and nibble arithmetic
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * ScaleByAltitude calls Multiply8x16 * ApplyFlightControl calls entry point Multiply8x16-6 * ProcessLanding (Part 7 of 7) calls entry point Multiply8x16-6 * ScaleFlightForces calls entry point Multiply8x16-6 * GetMoments calls entry point Multiply8x16-2

This routine multiplies an unsigned 8-bit and a signed 16-bit number, as follows: (G W V) = (Q P) * R It uses the following algorithm: (Q P) * R = (Q << 8 + P) * R = (Q << 8) * R + (P * R) = (Q * R) << 8 + (P * R) Arguments: (Q P) A signed 16-bit number R An unsigned 8-bit number Returns: (G W V) The result, (Q P) * R A The high byte of the result (G) Other entry points: Multiply8x16-2 Store X in VV before doing the calculation Multiply8x16-6 Store X in VV and calculate (G W V) = (A Y) * R
STY P \ Set (Q P) = (A Y) STA Q STX VV \ Store X in VV .Multiply8x16 LDX Q \ Set X to the high byte of the argument in (Q P) BPL muly1 \ If X is positive, jump to muly1 to skip the following LDA #0 \ Set (X P) = 0 - (Q P) SEC \ SBC P \ Starting with the low bytes STA P LDA #0 \ And then the high bytes SBC Q TAX .muly1 \ By this point, (X P) is positive, and we have: \ \ (X P) = |Q P| LDY R \ Set (A V) = X * Y JSR Multiply8x8 \ = |Q| * R STA G \ Set (G W) = (A V) LDA V \ = |Q| * R STA W LDY R \ Set (A V) = X * Y LDX P \ = P * R JSR Multiply8x8 \ We now calculate the following: \ \ (G W V) = (G W 0) + (0 A V) \ = (G W) << 8 + (P * R) \ = (|Q| * R) << 8 + (P * R) \ \ which is the result we want \ \ We we don't need to calculate the lowest bytes, as we \ already know that V + 0 = V, so we just do the middle \ and high bytes CLC \ Set (G W V) = (G W 0) + (0 A V) ADC W \ STA W \ starting with the middle bytes LDA #0 \ And then the top bytes ADC G STA G LDX Q \ If the original argument (Q P) was positive, the BPL GetMoments-1 \ result already has the correct sign, so return from \ the subroutine (as GetMoments-1 contains an RTS) LDA #0 \ Otherwise we want to negate (G W V), so start with by SEC \ negating V SBC V STA V \ And fall through into Negate16Bit to negate (G W) and \ return that as our result