( use short as a fixed point number 8.8 ) ( ) ( so #0001 is interpreted as 1/256 ) ( and #ffff is interpreted as 255+255/256 ) ( ) ( x = x0 + x1/256 ) ( y = y0 + y1/256 ) ( ) ( many 8.8 operations are equivalent to u16: ) ( * comparisons/equality ) ( * addition/subtraction ) ( ) ( but due to 16-bit truncation multiplication is different. ) ( ) ( x*y = x0*y0 + x0*y1/256 + x1*y0/256 + x1*y1/65536 ) ( ) ( since we only have 16-bits: ) ( 1. we need to drop the 8 high bits from x0*y0 ) ( 2. we need to drop the 8 low bits from x1*y1 ) ( 3. we need to use all the bits from x0*y1 and x1*y0 ) %EMIT { #18 DEO } %DIGIT { #00 SWP ;digits ADD2 LDA EMIT } %SPACE { #20 EMIT } %NEWLINE { #0a EMIT } %EMIT-BYTE { DUP #04 SFT DIGIT #0f AND DIGIT } ( program ) |0100 #0100 #0100 ;mul-fix JSR2 ;emit-short JSR2 NEWLINE #0999 #0100 ;mul-fix JSR2 ;emit-short JSR2 NEWLINE #abcd #0100 ;mul-fix JSR2 ;emit-short JSR2 NEWLINE #0200 #0200 ;mul-fix JSR2 ;emit-short JSR2 NEWLINE #0400 #0200 ;mul-fix JSR2 ;emit-short JSR2 NEWLINE BRK %LO { NIP #00 SWP } %HI { POP #00 SWP } @mul-fix ( x* y* -> z* ) OVR2 OVR2 LO SWP2 LO MUL2 ( x1*y1 ) #08 SFT2 STH2 ( z = (x1*y1)>>8 ) OVR2 OVR2 HI SWP2 LO MUL2 ( x0*y1 ) STH2 ADD2r ( z += x0*y1 ) OVR2 OVR2 LO SWP2 HI MUL2 ( x1*y0 ) STH2 ADD2r ( z += x1*y0 ) HI SWP2 HI MUL2 ( x0*y0 ) #80 SFT2 STH2r ADD2 ( z += (x0*y0)<<8 ) JMP2r @emit-short SWP EMIT-BYTE EMIT-BYTE JMP2r ( convenience for less branching when printing hex ) @digits 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66