Skip to navigation

Elite on the BBC Micro and NES

Maths (Arithmetic): FMLTU

[NES version, Bank 7]

Name: FMLTU [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate A = A * Q / 256 Deep dive: Multiplication and division using logarithms
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DOEXP calls FMLTU * DrawLightning calls FMLTU * LL51 calls FMLTU * LL9 (Part 5 of 12) calls FMLTU * MVEIT (Part 3 of 9) calls FMLTU * PLS22 calls FMLTU

Do the following multiplication of two unsigned 8-bit numbers, returning only the high byte of the result: (A ?) = A * Q or, to put it another way: A = A * Q / 256 The Master and 6502 Second Processor versions use logarithms to speed up the multiplication process. See the deep dive on "Multiplication using logarithms" for more details.
Returns: C flag The C flag is clear if A = 0, or set if we return a result from one of the log tables
.FMLTU STX P ; Store X in P so we can preserve it through the call to ; FMULTU STA widget ; Store A in widget, so now widget = argument A TAX ; Transfer A into X, so now X = argument A BEQ MU3 ; If A = 0, jump to MU3 to return a result of 0, as ; 0 * Q / 256 is always 0 ; We now want to calculate La + Lq, first adding the low ; bytes (from the logL table), and then the high bytes ; (from the log table) LDA logL,X ; Set A = low byte of La ; = low byte of La (as we set X to A above) LDX Q ; Set X = Q BEQ MU3again ; If X = 0, jump to MU3again to return a result of 0, as ; A * 0 / 256 is always 0 CLC ; Set A = A + low byte of Lq ADC logL,X ; = low byte of La + low byte of Lq BMI oddlog ; If A > 127, jump to oddlog LDA log,X ; Set A = high byte of Lq LDX widget ; Set A = A + C + high byte of La ADC log,X ; = high byte of Lq + high byte of La + C ; ; so we now have: ; ; A = high byte of (La + Lq) BCC MU3again ; If the addition fitted into one byte and didn't carry, ; then La + Lq < 256, so we jump to MU3again to return a ; result of 0 and the C flag clear ; If we get here then the C flag is set, ready for when ; we return from the subroutine below TAX ; Otherwise La + Lq >= 256, so we return the A-th entry LDA antilog,X ; from the antilog table LDX P ; Restore X from P so it is preserved RTS ; Return from the subroutine .oddlog LDA log,X ; Set A = high byte of Lq LDX widget ; Set A = A + C + high byte of La ADC log,X ; = high byte of Lq + high byte of La + C ; ; so we now have: ; ; A = high byte of (La + Lq) BCC MU3again ; If the addition fitted into one byte and didn't carry, ; then La + Lq < 256, so we jump to MU3again to return a ; result of 0 and the C flag clear ; If we get here then the C flag is set, ready for when ; we return from the subroutine below TAX ; Otherwise La + Lq >= 256, so we return the A-th entry LDA antilogODD,X ; from the antilogODD table .MU3 ; If we get here then A (our result) is already 0 LDX P ; Restore X from P so it is preserved RTS ; Return from the subroutine .MU3again LDA #0 ; Set A = 0 LDX P ; Restore X from P so it is preserved RTS ; Return from the subroutine