Submitted by Steve Fewell
Routine: imult
Name: Integer Multiplication
Starting Address: &9F64
Entry criteria: IWA contains the first Integer number. Y contains the
Most Significant Byte of this Integer number (?&2D). ?&4 and ?&5 point
to the second Integer variable. ?&27 = 4, X = &4.
Notes: If the IWA > &FFFF, it is truncated to 16 bits.
Exit: IWA contains the result of [Integer variable * IWA]
Description:
Exclusive-OR the Most significant bytes of both integers together, this determines
the sign of the result (if only one of the MSBs is negative then the result
is negative, otherwise it is positive).
Make both integers positive [using ipos] (so that we only have to do positive multiplication).
Store the multiplier in zero-page locations (&39 to &3C) and put the multiplicand into the IWA [popi].
Initialise the result to zero (The result is stored in Y [&3D], X [&3E], &3F and &40).
Keep repeating the following loop until the multiplier is zero [only the least significant two bytes of the multiplier are used]:
(1) Divide the multiplier by 2 (and make the result integer)
(2) If an integer result was not obtained, (i.e. Multiplier was an odd number before division) then add the multiplicand to the result. [Dividing the multiplier lost 0.5 of its value, so we add on the multiplicand (which at this stage is worth 0.5 * the actual multiplicand) before it is multiplied to perform the multiplication of the lost 0.5 of the multiplier].
(3) Multiply the multiplicand by 2
Until multiplier is zero ((&39 OR &3A) = zero).
Retrieve the result from the zero page locations (&3D to &40) and make it negative if the sign [at the beginning] was determined to be negative.
Jump to &9FCA to test the value of X [the next operator] when the routine was entered. If X contains the operator code for '*', '/', 'MOD' or 'DIV' then send the result to the appropriate routine, for further calculation, otherwise exit the multiplication routine.
Disassembly for the integer multiplication routine
9F64 | Z | 90 | 5A | PHY |
9F65 | 032 190 172 | 20 BE AC | JSR &ACBE Make IWA value positive [ipos] | |
9F68 | ' | 134 039 | 86 27 | STX &27 |
9F6A | 9 | 162 057 | A2 39 | LDX#&39 |
9F6C | 032 198 189 | 20 C6 BD | JSR &BDC6 Save Integer (IWA) to zero page location [izpout] | |
9F6F | 032 230 188 | 20 E6 BC | JSR &BCE6 Retrieve IWA value from Stack[popi] | |
9F72 | h | 104 | 68 | PLA |
9F73 | E- | 069 045 | 45 2D | EOR &2D |
9F75 | 7 | 133 055 | 85 37 | STA &37 |
9F77 | 032 190 172 | 20 BE AC | JSR &ACBE Make the IWA value positive [ipos] | |
9F7A | 160 000 | A0 00 | LDY#&00 | |
9F7C | 162 000 | A2 00 | LDX#&00 | |
9F7E | d? | 100 063 | 64 3F | STZ &3F |
9F80 | d@ | 100 064 | 64 40 | STZ &40 |
9F82 | F: | 070 058 | 46 3A | LSR &3A |
9F84 | f9 | 102 057 | 66 39 | ROR &39 |
9F86 | 144 021 | 90 15 | BCC 21 --> &9F9D | |
9F88 | 24 | 18 | CLC | |
9F89 | 152 | 98 | TYA | |
9F8A | e* | 101 042 | 65 2A | ADC &2A |
9F8C | 168 | A8 | TAY | |
9F8D | 138 | 8A | TXA | |
9F8E | e+ | 101 043 | 65 2B | ADC &2B |
9F90 | 170 | AA | TAX | |
9F91 | ? | 165 063 | A5 3F | LDA &3F |
9F93 | e, | 101 044 | 65 2C | ADC &2C |
9F95 | ? | 133 063 | 85 3F | STA &3F |
9F97 | @ | 165 064 | A5 40 | LDA &40 |
9F99 | e- | 101 045 | 65 2D | ADC &2D |
9F9B | @ | 133 064 | 85 40 | STA &40 |
9F9D | * | 006 042 | 06 2A | ASL &2A |
9F9F | &+ | 038 043 | 26 2B | ROL &2B |
9FA1 | &, | 038 044 | 26 2C | ROL &2C |
9FA3 | &- | 038 045 | 26 2D | ROL &2D |
9FA5 | 9 | 165 057 | A5 39 | LDA &39 |
9FA7 | : | 005 058 | 05 3A | ORA &3A |
9FA9 | 208 215 | D0 D7 | BNE -41 --> &9F82 | |
9FAB | = | 132 061 | 84 3D | STY &3D |
9FAD | > | 134 062 | 86 3E | STX &3E |
9FAF | 7 | 165 055 | A5 37 | LDA &37 |
9FB1 | 8 | 8 | PHP | |
9FB2 | = | 162 061 | A2 3D | LDX#&3D |
9FB4 | 032 128 170 | 20 80 AA | JSR &AA80 Set the IWA to an Integer value at a zero-page location [izpin] | |
9FB7 | ( | 40 | 28 | PLP |
9FB8 | 016 003 | 10 03 | BPL 3 --> &9FBD | |
9FBA | 032 222 172 | 20 DE AC | JSR &ACDE icomp | |
9FBD | ' | 166 039 | A6 27 | LDX &27 |
9FBF | 128 009 | 80 09 | BRA 9 --> &9FCA | |
9FC1 | L; | 076 059 159 | 4C 3B 9F | JMP &9F3B '*' Operator |
9FC4 | & | 032 038 188 | 20 26 BC | JSR &BC26 Push IWA value to the BASIC Stack [pushi] |
9FC7 | 032 018 160 | 20 12 A0 | JSR &A012 | |
9FCA | * | 224 042 | E0 2A | CPX#&2A |
9FCC | 240 243 | F0 F3 | BEQ -13 --> &9FC1 | |
9FCE | / | 224 047 | E0 2F | CPX#&2F |
9FD0 | 240 009 | F0 09 | BEQ 9 --> &9FDB '/' Operator | |
9FD2 | 224 131 | E0 83 | CPX#&83 | |
9FD4 | 240 031 | F0 1F | BEQ 31 --> &9FF5 Integer MOD routine | |
9FD6 | 224 129 | E0 81 | CPX#&81 | |
9FD8 | # | 240 035 | F0 23 | BEQ 35 --> &9FFD Integer DIV routine |
9FDA | ` | 96 | 60 | RTS |