AppleIIAsm-Collection/documentation/AppleIIAsm Library Collecti.../0.6.1/33.0 Detailed_Reference_D4_...

174 KiB

Disk 4 : Basic Integer Math and Pseudorandom Numbers


Part I: The Math Collection

The fourth disk in the library is dedicated to Integer Math and Pseudorandom Number Generation. For the most part, this collection is limited to basic math routines only due to disk size constraints; the routines and macros for all of the current implementations already occupy most of the disk space available. This includes, somewhat meagerly, macros and subroutines for:

  • 8-bit Addition
  • 8-bit Subtraction
  • 8-bit Multiplication
  • 8-bit Division
  • 16-bit Addition
  • 16-bit Subtraction
  • 16-bit Multiplication
  • 16-bit Division
  • 8-bit Pseudorandom Number Generation
  • 16-bit Pseudorandom Number Generation
  • Ranged Pseudorandom Number Generation
  • Two Randomization Techniques

Currently, all operations are for unsigned integers, though this will likely be the last addition to the collection in the next revision (accounting for negative numbers requires using wrappers that predetermine the sign value before multiplying or dividing, making the added number of bytes somewhat trivial). While a math routine and macro disk is planned for the Extended AppleIIAsm Library disks, including routines for finding percentages, floating point math, greatest common factors and least common multiples and more, the appearance of the Extended Library disks will not be any time soon.


Math Components

The Math Collection contains the following components:

  • A header file that contains the various hooks, vectors and memory space used by the entire Math Collection.
  • Macros and subroutines for basic integer math as well as pseudorandom numbers. The basic math macros and subroutines are further separated into "math-by" items that calculate by a given integer constant and general purpose items that calculate by arbitrary numbers.
  • Demonstrations of all macros and subroutines in the collection, ordered by type: "math-by", general purpose basic math, and pseudorandom numbers.

Header File

The mathematics header file includes a number of vectors and spans of address space for use by the rest of the collection. The header is especially important for pseudorandom number generation, as it holds the location for the seed (both low byte and high byte) as well as a table used to determine the value to EOR the seed by in the process of number generation. This table is 64 bytes long, and contains "magic numbers" that allow for the generation of a complete set of 65,536 different numbers before being repeated, guaranteeing that 1) with the same number and EOR value, the number generated can be reproduced, which allows for stepping back and forth between the generated numbers if needed, and 2) maximum variability is achieved, although this may come at the cost of statistical unlikeliness. The table is used by the RNDMZ macro for randomization of the generator, but the EOR value can also be directly altered by the RNDEOR macro when a specific EOR value is desired.

Condition Value
Name File: HEAD.MATH.ASM
Type Header File
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin 8 Pro
OS Apple DOS 3.3
Purpose Provide appropriate hooks and routines for the Math collection
Dependencies none
Bytes 0
Notes Repeatedly used subroutines by the library may be placed here in the future
See Also none

DETAILS

Listing 4.0 provides the complete source of the header file.

Listing 4.0: HEAD.MATH.ASM Source

*
*``````````````````````````````*
* HEAD.MATH.ASM                *
*                              *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      22-MAR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
GETNUM   EQU   $FFA7      ; ASCII TO HEX IN 3E & 3F
RNDL     EQU   $4E        ; RANDOM NUMBER LOW
RNDH     EQU   $4F        ; RANDOM NUMBER HIGH
*
FAC      EQU   $9D        ; FLOATING POINT ACCUM
FSUB     EQU   $E7A7      ; FLOATING POINT SUBTRACT
FADD     EQU   $E7BE
FMULT    EQU   $E97F      ; FP MULTIPLY
FDIV     EQU   $EA66      ; FP DIVIDE
FMULTT   EQU   $E982
FDIVT    EQU   $EA69
FADDT    EQU   $E7C1
FSUBT    EQU   $E7AA
*
MOVFM    EQU   $EAF9      ; MOVE FAC > MEM
MOVMF    EQU   $EB2B      ; MOVE MEM > FAC
NORM     EQU   $E82E
CONUPK   EQU   $E9E3
*
FLOG     EQU   $E941      ; LOGARITHM
FSQR     EQU   $EE8D      ; SQUARE ROOT
FCOS     EQU   $EFEA      ; FP COSINE
FSIN     EQU   $EFF1      ; SINE
FTAN     EQU   $F03A      ; TANGENT
FATN     EQU   $F09E      ; ATANGENT
*
** THE FOLLOWING IS A SERIES OF "MAGIC NUMBERS"
** TO USE AS SEEDS FOR PSEUDO-RANDOM NUMBER GENERATION.
** THESE CAN BE FOUND ON CODEBASE64, BUT ARE KNOWN
** WELL ENOUGH TO BE CONSIDERED COMMON KNOWLEDGE.
*
         JMP   ]MATH_GO
]MAGEOR  HEX   002D
]MAGNUM  HEX   002D0039003F005300BD00D7012F013D
         HEX   014F015D019701A101AD01BF01C70215
         HEX   02190225022F025D026D0285029102A1
         HEX   02E5031D034B036903710387038D039F
         HEX   03A303DD03F904290457046704830489
         HEX   049104BF04C1053305470569058705C3
         HEX   05DD05EB0641064B0653068B06C3076B
         HEX   076D0779078307F1080D086108BF08D5
]MATH_GO
*


Macros and Subroutines

The Basic Math Collection is divided into six different macro categories: 8-bit basic math, 16-bit basic math, 8-bit constant operations, 16-bit constant operations, and pseudorandom number generation. As always, 8-bit operations should be used whenever possible, as significantly fewer bytes and cycles are used in comparison to 16-bit operations.

Additionally, math by constants should be used whenever one of the arguments is already known; that is, the programmer knows that something will be multiplied by three, or ten, or thirty. While macros do not exist for numbers above ten (except for 100), the answers can be easily derived from using two or more of the math-by macros. For instance, to get multiplication by thirty, first multiply by 10, then multiply that by three. Although this seems like extra work, the number of cycles saved here can be substantial, as compared to using the general purpose macros. If speed is a concern, then math-by-constants is the way to go.


Math By Constants Macros: 8-bit Division

These macros are dedicated to dividing a given 8-bit number by a known constant. Since the constant is known, we are able to precisely measure the number of cycles and bytes needed for the operation, and it takes significantly fewer of both to return a result than would using a general purpose division implementation.

It should be noted that these macros do not take sign into consideration, and there are no plans to make wrappers for the math-by macros; only unsigned numbers are accepted. For signed operations, either use the general purpose division macros or create wrappers specific to each divide-by-constant macro.

LISTING 4.10: MAC.D8BY.ASM Header Source

*
*``````````````````````````````*
* MAC.M8BY.ASM                 *
*                              *
* THESE MACROS CONSIST OF 8BIT *
* DIVISION BY A CONSTANT       *
* ROUTINES. WHILE SOME OF      *
* THESE ARE TRIVIAL, MOST HAVE *
* BEEN TAKEN FROM THE WORK OF  *
* OMEGAMATRIX AS SHARED ON     *
* THE NESDEV FORUMS. AS SUCH,  *
* LICENSING MAY VARY; HOWEVER, *
* SINCE THEY WERE FREELY       *
* SHARED, IT SHOULD BE SAFELY  *
* ASSUMED THAT THEY ARE PUBLIC *
* DOMAIN.                      *
*                              *
* NOTE: THESE ARE ^HIGHLY^     *
* OPTIMIZED BY BRUTE FORCE ON  *
* A MODERN SYSTEM, AND SOME OF *
* THESE MAY EXPLOIT QUIRKS OF  *
* THE 6502. TO SUM THAT UP:    *
* THESE ARE NOT ROUTINES THAT  *
* ARE EASILY CUT THROUGH BY A  *
* NOVICE, EVEN THOUGH THEY     *
* LOOK SIMPLE ENOUGH.          *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* (COPIED FROM OMEGAMATRIX)    *
*                              *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      29-MAR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* LIST OF MACROS               *
*                              *
*  D8BY2  : DIVIDE BY TWO      *
*  D8BY3  : DIVIDE BY THREE    *
*  D8BY4  : DIVIDE BY FOUR     *
*  D8BY5  : DIVIDE BY FIVE     *
*  D8BY6  : DIVIDE BY SIX      *
*  D8BY7  : DIVIDE BY SEVEN    *
*  D8BY8  : DIVIDE BY EIGHT    *
*  D8BY9  : DIVIDE BY NINE     *
*  D8BY10 : DIVIDE BY TEN      *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE D8BY2 MACRO

SUMMARY

Condition Value
Name D8BY2
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by two
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 6
Bytes 4
Notes None
See Also M8BY2 M16BY2

DETAILS

The D8BY2 macro divides a given number by two using a left shift (LSR). The result is floored, and no remainder is provided; it is passed back via the .A register.

LISTING 4.11: The D8BY2 Macro Source

*
*``````````````````````````````*
* D8BY2         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY TWO   *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 6                    *
* SIZE: 4 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY2    MAC
         LDA   ]1         ; {4C3B}
         LSR              ; {2C1B} SHIFT BITS RIGHT IN .A
                          ; TO DIVIDE BY TWO. ANSWER REMAINS
                          ; IN .A REGISTER
         <<<


THE D8BY3 MACRO

SUMMARY

Condition Value
Name D8BY3
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by three
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 29
Bytes 19
Notes None
See Also M8BY3 M16BY3

DETAILS

The DIV8BY3 macro divides a given 8-bit number by three.

LISTING 4.12: D8BY3 Macro Source

*
*``````````````````````````````*
* D8BY3         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY THREE *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 29                   *
* SIZE: 19 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY3    MAC
         LDA   ]1         ; {4C3B}
         CLC              ; {2C2B} CLEAR THE CARRY
         STA   BPAR1      ; {3C2B} STORE ORIG NUM IN Z PAGE
         LSR              ; {2C1B} DIVIDE .A BY TWO
         ADC   #21        ; {2C2B} ADD 21 AS A CORRECTION
         LSR              ; {2C1B} DIVIDE .A BY TWO
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL VALUE TO NEW
         ROR              ; {2C1B} ROTATE A TO NEXT BIT
         LSR              ; {2C1B} SHIFT RIGHT TO DIVIDE BY 2
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL VALUE
         ROR              ; {2C1B} ROTATE .A TO NEXT BIT
         LSR              ; {2C1B} DIVIDE BY 2
         <<<
*


THE D8BY4 MACRO

SUMMARY

Condition Value
Name D8BY4
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by four
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 8
Bytes 5
Notes None
See Also M8BY4 M16BY4

DETAILS

The DIV8BY4 macro divides a given 8-bit number by four.

LISTING 4.13: D8BY4 Macro Source

*
*``````````````````````````````*
* D8BY4         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY FOUR  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 8                    *
* SIZE: 5 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY4    MAC
         LDA   ]1         ; {4C3B}
         LSR              ; {2C1B} DIVIDE .A BY TWO
         LSR              ; {2C1B} DIVIDE .A BY TWO
         <<<
*


THE D8BY5 MACRO

SUMMARY

Condition Value
Name D8BY5
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by five
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 34
Bytes 21
Notes None
See Also M8BY5 M16BY5

DETAILS

The DIV8BY4 macro divides a given 8-bit number by five.

LISTING 4.14: D8BY5 Macro Source

*
*``````````````````````````````*
* D8BY5         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY FIVE  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 34                   *
* SIZE: 21 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY5    MAC
         LDA   ]1         ; {4C3B}
         STA   BPAR1      ; {3C2B} STORE ORIG ON ZERO PAGE
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   #13        ; {2C2B} ADD 13 AS A CORRECTIVE
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL
         ROR              ; {2C1B} ROTATE BITS RIGHT
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL VALUE
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         <<<
*


THE D8BY6 MACRO

SUMMARY

Condition Value
Name D8BY6
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by six
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 36
Bytes 21
Notes None
See Also M8BY6 M16BY6

DETAILS

The DIV8BY6 macro divides a given 8-bit number by six.

LISTING 4.15: D8BY5 Macro Source

*
*``````````````````````````````*
* D8BY6         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY SIX   *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 36                   *
* SIZE: 21 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY6    MAC
         LDA   ]1         ; {4C3B}
         CLC              ; {2C1B}
         LSR              ; {2C1B} DIVIDE .A BY TWO
         STA   BPAR1      ; {3C2B} STORE IN ZERO PAGE
         LSR              ; {2C1B} DIVIDE AGAIN
         LSR              ; {2C1B} DIVIDE AGAIN
         ADC   BPAR1      ; {3C2B} ADD VALUE/2
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   BPAR1      ; {3C2B} ADD VALUE/2
         ROR              ; {2C1B} ROTATE RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   BPAR1      ; {3C2B} ADD VALUE/2
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         <<<
*


THE D8BY7 MACRO

SUMMARY

Condition Value
Name D8BY7
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by seven
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 33
Bytes 19
Notes None
See Also M8BY7 M16BY7

DETAILS

The DIV8BY7 macro divides a given 8-bit number by seven.

LISTING 4.16: D8BY7 Macro Source

*
*``````````````````````````````*
* D8BY7         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY SEVEN *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 33                   *
* SIZE: 19 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY7    MAC
         LDA   ]1         ; {4C3B}
         CLC              ; {2C1B} CLEAR CARRY
         STA   BPAR1      ; {3C2B} STORE NUMBER IN ZERO PAGE
         LSR              ; {2C1B} DIVIDE .A BY TWO
         LSR              ; {2C1B} AGAIN
         LSR              ; {2C1B} AGAIN
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         <<<
*


THE D8BY8 MACRO

SUMMARY

Condition Value
Name D8BY8
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by eight
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 10
Bytes 6
Notes None
See Also M8BY8 M16BY8

DETAILS

The DIV8BY8 macro divides a given 8-bit number by eight.

LISTING 4.17: D8BY8 Macro Source

*
*``````````````````````````````*
* D8BY8         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY EIGHT *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 10                   *
* SIZE: 6 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY8    MAC
         LDA   ]1         ; {4C3B}
         LSR              ; {2C1B} DIVIDE .A BY TWO (2)
         LSR              ; {2C1B} DIVIDE BY TWO (4)
         LSR              ; {2C1B} DIVIDE BY TWO (8)
         <<<
*


THE D8BY9 MACRO

SUMMARY

Condition Value
Name D8BY9
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by nine
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 36
Bytes 21
Notes None
See Also M8BY9 M16BY9

DETAILS

The DIV8BY9 macro divides a given 8-bit number by nine.

LISTING 4.18: D8BY9 Macro Source

*
*``````````````````````````````*
* D8BY9         (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY NINE  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 36                   *
* SIZE: 21 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY9    MAC
         LDA   ]1         ; {4C3B}
         CLC              ; {2C1B} CLEAR CARRY
         STA   BPAR1      ; {3C2B} STORE .A IN ZERO PAGE
         LSR              ; {2C1B} DIVIDE .A BY TWO
         LSR              ; {2C1B} AGAIN
         LSR              ; {2C1B} AGAIN
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER
         ROR              ; {2C1B} ROTATE BITS RIGHT
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER
         ROR              ; {2C1B} ROTATE BITS RIGHT
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         <<<
*


THE D8BY10 MACRO

SUMMARY

Condition Value
Name D8BY10
Type Macro
File MAC.D8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide an 8-bit value by ten
Input ]1 = Number to divide
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 36
Bytes 21
Notes None
See Also M8BY10 M16BY10

DETAILS

The DIV8BY10 macro divides a given 8-bit number by ten.

LISTING 4.19: D8BY10 Macro Source

*
*``````````````````````````````*
* D8BY10        (NATHAN RIGGS) *
*                              *
* DIVIDE 8-BIT NUMBER BY TEN   *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO DIVIDE       *
*                              *
* CYCLES: 36                   *
* SIZE: 21 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
D8BY10   MAC
         CLC              ; {2C1B} CLEAR CARRY
         LDA   ]1         ; {4C3B}
         LSR              ; {2C1B} DIVIDE .A BY TWO
         STA   BPAR1      ; {3C2B} STORE IN ZERO PAGE
         LSR              ; {2C1B} DIVIDE .A BY TWO
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL/2
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL/2
         ROR              ; {2C1B} ROTATE BITS RIGHT
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL/2
         ROR              ; {2C1B} ROTATE BITS RIGHT
         LSR              ; {2C1B} DIVIDE BY TWO
         LSR              ; {2C1B} DIVIDE BY TWO
         <<<


Math By Constants Macros: 8-bit Multiplication

These macros are dedicated to multiplying a given 8-bit number by a known constant. Since the constant is known, we are able to precisely measure the number of cycles and bytes needed for the operation, and it takes significantly fewer of both to return a result than would using a general purpose multiplication implementation. It should be noted that these macros do not take sign into consideration, and there are no plans to make wrappers for the math-by macros; only unsigned numbers are accepted. For signed operations, either use the general purpose division macros or create wrappers specific to each divide-by-constant macro.

In the comments of each macro, a formula is provided that shows, mathematically, how the algorithm works. In simple terms: since the 6502 runs on binary, it can divide and multiply only by two on its own. Thus, any division or multiplication ultimately has to reduce an equation to factors of two, plus or minus the original value passed at times.

LISTING 4.20: MAC.D8BY.ASM Header Source

*
*``````````````````````````````*
* MAC.M8BY.ASM                 *
*                              *
* THESE MACROS ARE FOR QUICKLY *
* CALCULATING A NUMBER BY A    *
* CONSTANT VALUE. THIS IS      *
* OFTEN FASTER THAN THE ALL-   *
* PURPOSE IMPLEMENTATIONS DUE  *
* TO KNOWING EXACTLY HOW MANY  *
* SHIFTS AND ROTATES ARE       *
* NEEDED, ADDITIONS, ETC.      *
*                              *
* NOTE THAT THIS IS FOR 8-BIT  *
* VALUES ONLY, AND ALL ANSWERS *
* ARE RETURNED IN THE .A       *
* REGISTER. .X IS SOMETIMES    *
* DESTROYED AS WELL.           *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      29-MAR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* LIST OF MACROS               *
*                              *
*  M8BY2  : MULTIPLY BY TWO    *
*  M8BY3  : MULTIPLY BY THREE  *
*  M8BY4  : MULTIPLY BY FOUR   *
*  M8BY5  : MULTIPLY BY FIVE   *
*  M8BY6  : MULTIPLY BY SIX    *
*  M8BY7  : MULTIPLY BY SEVEN  *
*  M8BY8  : MULTIPLY BY EIGHT  *
*  M8BY9  : MULTIPLY BY NINE   *
*  M8BY10 : MULTIPLY BY TEN    *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE M8BY2 MACRO

SUMMARY

Condition Value
Name M8BY2
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by two
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 6
Bytes 4
Notes None
See Also D8BY2 M16BY2

DETAILS

The MUL8BY2 macro multiplies a given 8-bit number by two.

LISTING 4.21: M8BY2 Macro Source

*
*``````````````````````````````*
* M8BY2         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* TWO. ONLY RETURNS 8-BIT      *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 6                    *
* SIZE: 4 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY2    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER
         ASL              ; {2C1B} SHIFT LEFT TO MUL BY 2
                          ; ANSWER HELD IN .A REGISTER
         <<<
*


THE M8BY3 MACRO

SUMMARY

Condition Value
Name M8BY3
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by three
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 6
Bytes 4
Notes None
See Also D8BY3 M16BY3

DETAILS

The MUL8BY3 macro multiplies a given 8-bit number by three.

LISTING 4.22: M8BY3 Macro Source

*
*``````````````````````````````*
* M8BY3         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* THREE. ONLY RETURNS 8-BIT    *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 13                   *
* SIZE: 9 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY3    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER
         STA   BPAR1      ; {3C2B} BACKUP IN BPAR1
         ASL              ; {2C1B} MUL 1ST ARGUMENT BY 2
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {2C2B} ADD ORIGINAL NUMBER
                          ; ANSWER HELD IN .A REGISTER
         <<<
*


THE M8BY4 MACRO

SUMMARY

Condition Value
Name M8BY4
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by four
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 8
Bytes 5
Notes None
See Also D8BY4 M16BY4

DETAILS

The MUL8BY4 macro multiplies a given 8-bit number by four.

LISTING 4.23: M8BY4 Macro Source

*
*``````````````````````````````*
* M8BY4         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* FOUR. ONLY RETURNS 8-BIT     *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 8                    *
* SIZE: 5 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY4    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         ASL              ; {2C1B} MUL AGAIN BY TWO (SO, FOUR)
                          ; ANSWER HELD IN .A
         <<<
*


THE M8BY5 MACRO

SUMMARY

Condition Value
Name M8BY5
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by five
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 15
Bytes 10
Notes None
See Also D8BY5 M16BY5

DETAILS

The MUL8BY5 macro multiplies a given 8-bit number by five.

LISTING 4.25: M8BY5 Macro Source

*
*``````````````````````````````*
* M8BY5         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* FIVE. ONLY RETURNS 8-BIT     *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 15                   *
* SIZE: 10 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY5    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         STA   BPAR1      ; {3C2B} STORE ORIG VAL IN BPAR1
         ASL              ; {2C1B} MULTIPLY BY TWO
         ASL              ; {2C1B} MUL BY TWO (SO, FOUR)
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {2C2B} ADD ORIGINAL VALUE TO NEW
                          ; ANSWER HELD IN .A
         <<<
*


THE M8BY6 MACRO

SUMMARY

Condition Value
Name M8BY6
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by six
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 15
Bytes 10
Notes None
See Also D8BY6 M16BY6

DETAILS

The MUL8BY6 macro multiplies a given 8-bit number by six.

LISTING 4.25: M8BY6 Macro Source

*
*``````````````````````````````*
* M8BY6         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* SIX. ONLY RETURNS 8-BIT      *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 27                   *
* SIZE: 18 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY6    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         STA   BPAR1      ; {3C2B} STORE ORIG IN BPAR1
         ASL              ; {2C1B} MULTIPLY .A BY TWO
         ASL              ; {2C1B} DO AGAIN TO MUL BY FOUR
         TAX              ; {2C1B} TRANSFER ANSWER INTO .X
         LDA   BPAR1      ; {3C2B} RELOAD ORIGINAL IN .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   BPAR1      ; {3C2B} STORE BACK INTO BPAR1
         TXA              ; {2C1B} TRANSFER .X BACK TO .A
         CLC              ; {2C1B} CLEAR THE CARRY
         ADC   BPAR1      ; {2C3B} ADD SECOND ARGUMENT ANSWER
         <<<
*


THE M8BY7 MACRO

SUMMARY

Condition Value
Name M8BY7
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by seven
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 133
Bytes 20
Notes None
See Also D8BY7 M16BY7

DETAILS

The MUL8BY7 macro multiplies a given 8-bit number by seven.

LISTING 4.28: M8BY7 Macro Source

*
*``````````````````````````````*
* M8BY7         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* SEVEN. ONLY RETURNS 8-BIT    *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 33                   *
* SIZE: 20 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY7    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         STA   BPAR1      ; {3C2B} STORE IN ZERO PAGE
         ASL              ; {2C1B} MULTIPLY NUM BY TWO
         ASL              ; {2C1B} AND AGAIN, SO BY FOUR
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER TO VALUE
         TAX              ; {2C1B} TEMPORARY TRANSFER TO .X
         LDA   BPAR1      ; {3C2B} LOAD ORIGINAL NUMBER IN .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   BPAR1      ; {3C2B} STORE IN ZERO PAGE
         TXA              ; {2C1B} TRANSFER .X BACK INTO .A
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {3C2B} ADD OTHER ARGUMENT SAVED IN MEM
                          ; ANSWER IS HELD IN .A REGISTER
         <<<
*


THE M8BY8 MACRO

SUMMARY

Condition Value
Name M8BY8
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by eight
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 10
Bytes 6
Notes None
See Also D8BY8 M16BY8

DETAILS

The MUL8BY8 macro multiplies a given 8-bit number by eight.

LISTING 4.29: M8BY8 Macro Source

*
*``````````````````````````````*
* M8BY8         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* EIGHT. ONLY RETURNS 8-BIT    *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 10                   *
* SIZE: 6 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY8    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         ASL              ; {2C1B} MULTIPLY BY 2 (SO FOUR)
         ASL              ; {2C1B} MULTIPLY BY 2 (SO EIGHT)
                          ; ANSWER IS HELD IN THE .A REGISTER
         <<<
*


THE M8BY9 MACRO

SUMMARY

Condition Value
Name M8BY9
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by nine
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 18
Bytes 11
Notes None
See Also D8BY9 M16BY9

DETAILS

The MUL8BY9 macro multiplies a given 8-bit number by nine.

LISTING 4.30: M8BY9 Macro Source

*
*``````````````````````````````*
* M8BY9         (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* NINE. ONLY RETURNS 8-BIT     *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 18                   *
* SIZE: 11 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY9    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         STA   BPAR1      ; {3C2B} TEMPORARY HOLD IN ZERO PAGE
         ASL              ; {2C1B} MULTIPLY BY 2 (2)
         ASL              ; {2C1B} MULTIPLY BY 2 (4)
         ASL              ; {2C1B} MULTIPLY BY 2 (8)
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL VALUE
                          ; ANSWER IS HELD IN .A REGISTER
         <<<
*


THE M8BY10 MACRO

SUMMARY

Condition Value
Name M8BY10
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply an 8-bit value by ten
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 18
Bytes 11
Notes None
See Also D8BY10 M16BY10

DETAILS

The MUL8BY10 macro multiplies a given 8-bit number by ten.

LISTING 4.30: M8BY10 Macro Source

*
*``````````````````````````````*
* M8BY10        (NATHAN RIGGS) *
*                              *
* MULTIPLY AN 8-BIT VALUE BY   *
* TEN. ONLY RETURNS 8-BIT      *
* PRODUCTS.                    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER TO MULTIPLY     *
*                              *
* CYCLES: 18                   *
* SIZE: 11 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
M8BY10   MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         STA   BPAR1      ; {3C2B} STORE IT IN ZERO PAGE
         ASL              ; {2C1B} MULTIPLY BY TWO (2)
         ASL              ; {2C1B} MULTIPLY BY TWO (4)
         CLC              ; {2C1B} CLEAR CARRY
         ADC   BPAR1      ; {3C2B} ADD ORIGINAL NUMBER TO VALUE
         ASL              ; {2C1B} AND MULTIPLY TOTAL BY TWO
                          ; ANSWER IS HELD IN .A REGISTER
         <<<
*

Math By Constants Macros: 16-bit Multiplication

These macros are dedicated to multiplying a given 16-bit number by a known constant. Since the constant is known, we are able to precisely measure the number of cycles and bytes needed for the operation, and it takes significantly fewer of both to return a result than would using a general purpose multiplication implementation. It should be noted that these macros do not take sign into consideration, and there are no plans to make wrappers for the math-by macros; only unsigned numbers are accepted. For signed operations, either use the general purpose division macros or create wrappers specific to each divide-by-constant macro.

In the comments of each macro, a formula is provided that shows, mathematically, how the algorithm works. In simple terms: since the 6502 runs on binary, it can divide and multiply only by two on its own. Thus, any division or multiplication ultimately has to reduce an equation to factors of two, plus or minus the original value passed at times.

LISTING 4.40: MAC.D8BY.ASM Header Source

*
*``````````````````````````````*
* MAC.M16BY.ASM                *
*                              *
* THESE MACROS ARE FOR FASTER  *
* MULTIPLICATION THROUGH USE   *
* OF KNOWN CONSTANTS. THIS WAY *
* IS FASTER THAN USUAL ALL-    *
* PURPOSE IMPLEMENTATIONS DUE  *
* TO CYCLES SAVED FROM NO      *
* LOOPS, TRACKING, ETC., AND   *
* ARE MEANT AS A POSSIBLE      *
* ALTERNATIVE TO THE REGULAR   *
* MULTIPLICATION ROUTINE IF    *
* NECESSARY.                   *
*                              *
* NOTE THAT THIS IS FOR 16-BIT *
* NUMBERS. ADDITIONALLY, THE   *
* FINAL ANSWER IS PLACED IN    *
* THE .X REGISTER (HIGH BYTE)  *
* AND .Y REGISTER (LOW BYTE).  *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      25-MAR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* LIST OF MACROS               *
*                              *
*  MBY2  : MULTIPLY BY TWO     *
*  MBY3  : MULTIPLY BY THREE   *
*  MBY4  : MULTIPLY BY FOUR    *
*  MBY5  : MULTIPLY BY FIVE    *
*  MBY6  : MULTIPLY BY SIX     *
*  MBY7  : MULTIPLY BY SEVEN   *
*  MBY8  : MULTIPLY BY EIGHT   *
*  MBY9  : MULTIPLY BY NINE    *
*  MBY10 : MULTIPLY BY TEN     *
*  MBY1H : MULTIPLY BY 100     *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE M16BY2 MACRO

SUMMARY

Condition Value
Name M16BY2
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 2
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 20
Bytes 13
Notes None
See Also D8BY2 M8BY2

DETAILS

The MUL16BY2 macro multiplies a given 16-bit number by two.

LISTING 4.41: M16BY2 Macro Source

*
*``````````````````````````````*
* MBY2          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* TWO.                         *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 20                   *
* SIZE: 13 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY2     MAC
         LDA   ]1         ; {4C3B} LOAD LOW BYTE IN .A
         ASL              ; {2C1B} MULTIPLY IT BY TWO
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} ADJUST FOR CARRY AND MULTIPLY
         TAX              ; {2C1B} TRANSFER HIGH BYTE TO .X REGISTER
         LDA   WPAR1      ; {3C2B} HOLD LOW BYTE IN .A
         <<<
*


THE M16BY3 MACRO

SUMMARY

Condition Value
Name M16BY3
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 3
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 47
Bytes 32
Notes None
See Also D8BY3 M8BY3

DETAILS

The MUL16BY2 macro multiplies a given 16-bit number by three.

LISTING 4.42: M16BY3 Macro Source

*
*``````````````````````````````*
* MBY3          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* THREE.                       *
*                              *
* FORMULA: 3X = 2X +X          *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 47                   *
* SIZE: 32 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY3     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         STA   WPAR1      ; {3C2B} STORE IT ON ZERO PAGE
         ASL              ; {2C1B} NOW MULTIPLY BY TWO
         STA   WPAR2      ; {3C2B} STORE IN 2ND ZERO PAGE LOC
         LDA   ]1+1       ; {4C3B} GET NUMBER HIGH BYTE
         STA   WPAR1+1    ; {3C2B} STORE HIGH BYTE ON ZERO PAGE
         ROL              ; {2C1B} ADJUST FOR CARRY AND MULTIPLY
         STA   WPAR2+1    ; {3C2B} STORE HIGH BYTE IN 2ND LOCATION
         LDA   WPAR1      ; {4C3B} LOAD ORIGINAL NUMBER IN .A
         CLC              ; {2C2B} CLEAR CARRY
         ADC   WPAR2      ; {3C2B} ADD SECOND NUMBER TO ORIGINAL
         STA   WPAR1      ; {3C2B} STORE LOW BYTE IN ZERO PAGE
         LDA   WPAR1+1    ; {3C2B} LOAD NUMBER HIGH BYTE IN .A
         ADC   WPAR2+1    ; {3C2B} ADD 2ND VALUE HIGH BYTE TO IT
         TAX              ; {2C1B} TRANSFER NEW HIGH BYTE TO .X
         LDA   WPAR1      ; {3C2B} RELOAD LOW BYTE IN .A
         <<<
*


THE M16BY4 MACRO

SUMMARY

Condition Value
Name M16BY4
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 4
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 37
Bytes 24
Notes None
See Also D8BY4 M8BY4

DETAILS

The MUL16BY4 macro multiplies a given 16-bit number by four.

LISTING 4.43: M16BY4 Macro Source

*
*``````````````````````````````*
* MBY4          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* FOUR.                        *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 37                   *
* SIZE: 24 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY4     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE TO .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   BPAR1      ; {3C2B} STORE LOW BYTE TO ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} ADJUST FOR CARRY AND MUL
         TAX              ; {2C1B} TRANSFER HIGH BYTE TO .X
         LDA   BPAR1      ; {4C3B} RELOAD LOW BYTE
         ASL              ; {2C1B} MULTIPLY AGAIN
         STA   BPAR1      ; {4C3B} STORE BACK ON ZERO PAGE
         TXA              ; {2C1B} TRANSFER HIGH BYTE BACK TO .A
         ROL              ; {2C1B} ADJUST FOR CARRY AND MULTIPLY
         TAX              ; {2C1B} TRANSFER HIGH BYTE BACK TO .X
         LDA   BPAR1      ; {4C3B} RELOAD LOW BYTE IN .A
         <<<
*


THE M16BY5 MACRO

SUMMARY

Condition Value
Name M16BY5
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 5
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 46
Bytes 30
Notes None
See Also D8BY5 M8BY5

DETAILS

The MUL16BY5 macro multiplies a given 16-bit number by five.

LISTING 4.44: M16BY5 Macro Source

*
*``````````````````````````````*
* MBY5          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* FIVE.                        *
*                              *
* FORMULA: 5X = 4X + X         *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 46                   *
* SIZE: 30 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY5     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MULTIPLY
         STA   WPAR1+1    ; {3C2B} STORE ON ZERO PAGE
         ASL   WPAR1      ; {2C1B} MULTIPLY LOW BYTE BY TWO AGAIN
         ROL   WPAR1+1    ; {2C1B} AND HIGH BYTE AGAIN
         LDA   WPAR1      ; {4C3B} LOAD LOW BYTE INTO .A
         CLC              ; {2C1B} CLEAR THE CARRY
         ADC   ]1         ; {3C2B} ADD ORIGINAL VALUE
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE IN .A
         ADC   ]1+1       ; {4C3B} ADD ORIGINAL HIGH BYTE
         TAX              ; {2C1B} TRANSFER HIGH BYTE TO .X
         LDA   WPAR1      ; {3C2B} LOAD LOW BYTE BACK IN .A
         <<<
*


THE M16BY6 MACRO

SUMMARY

Condition Value
Name M16BY6
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 6
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 58
Bytes 38
Notes None
See Also D8BY6 M8BY6

DETAILS

The MUL16BY6 macro multiplies a given 16-bit number by six.

LISTING 4.45: M16BY6 Macro Source

*
*``````````````````````````````*
* MBY6          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* SIX.                         *
*                              *
* FORMULA: 6X = 2(2X + X)      *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 58                   *
* SIZE: 38 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY6     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD HIGH BYTE
         ROL              ; {2C1B} ADJUST CARRY AND MULTIPLY
         STA   WPAR1+1    ; {3C2B} STORE ON ZERO PAGE
         LDA   WPAR1      ; {3C2B} RELOAD LOW BYTE IN .A
         CLC              ; {2C1B} CLEAR THE CARRY
         ADC   ]1         ; {4C3B} ADD ORIGINAL LOW BYTE
         STA   WPAR1      ; {3C2B} STORE BACK ON ZERO PAGE
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE AGAIN
         ADC   ]1+1       ; {4C3B} ADD ORIGINAL HIGH BYTE
         STA   WPAR1+1    ; {3C2B} STORE ON ZERO PAGE
         LDA   WPAR1      ; {3C2B} LOAD LOW BYTE AGAIN
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MULTIPLY
         TAX              ; {2C1B} HOLD HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} RELOAD LOW BYTE IN .A
         <<<
*


THE M16BY7 MACRO

SUMMARY

Condition Value
Name M16BY7
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 7
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 72
Bytes 47
Notes None
See Also D8BY7 M8BY7

DETAILS

The MUL16BY7 macro multiplies a given 16-bit number by seven.

LISTING 4.46: M16BY7 Macro Source

*
*``````````````````````````````*
* MBY7          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* SEVEN.                       *
*                              *
* FORMULA: 7X = 4X + 2X + X    *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 72                   *
* SIZE: 47 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY7     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE IN .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE IN ZERO PAGE
         STA   WPAR2      ; {3C2B} STORE IN 2ND ZP LOCATION
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MULTIPLY
         STA   WPAR1+1    ; {3C2B} STORE IN 1ST ZP HIGH BYTE LOC
         STA   WPAR2+1    ; {3C2B} STORE IN 2ND ZP HIGH BYTE LOC
         ASL   WPAR1      ; {2C1B} MULTIPLY 1ST LOC BY TWO
         ROL   WPAR1+1    ; {2C1B} ALSO HIGH BYTE
         LDA   ]1         ; {4C3B} LOAD ORIGINAL NUMBER
         CLC              ; {2C1B} CLEAR CARRY
         ADC   WPAR1      ; {3C2B} ADD FIRST LOC TO NUMBER LOW BYTE
         STA   WPAR1      ; {3C2B} STORE IN 1ST LOC
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ADC   WPAR1+1    ; {3C2B} ADD 1ST LOC HIGH BYTE
         STA   WPAR1+1    ; {3C2B} AND STORE IN 1ST LOC
         LDA   WPAR1      ; {3C2B} RELOAD NEW LOW BYTE
         CLC              ; {2C1B} CLEAR CARRY
         ADC   WPAR2      ; {3C2B} ADD SECOND LOC LOW BYTE
         STA   WPAR1      ; {3C2B} STORE IN 1ST LOC LOW BYTE
         LDA   WPAR1+1    ; {3C2B} LOAD 1ST LOC HIGH BYTE
         ADC   WPAR2+1    ; {3C2B} ADD 2ND LOC HIGH BYTE
         TAX              ; {2C1B} HOLD FINAL HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} HOLD FINAL LOW BYTE IN .A
         <<<
*


THE M16BY8 MACRO

SUMMARY

Condition Value
Name M16BY8
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 8
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 34
Bytes 21
Notes None
See Also D8BY8 M8BY8

DETAILS

The MUL16BY8 macro multiplies a given 16-bit number by eight.

LISTING 4.47: M16BY8 Macro Source

*
*``````````````````````````````*
* MBY8          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* EIGHT.                       *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 34                   *
* SIZE: 21 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY8     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE IN ZP LOC
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MUL BY 2
         STA   WPAR1+1    ; {3C2B} STORE IN ZP LOC
         ASL   WPAR1      ; {2C1B} MULTIPLY LOW BYTE BY 2
         ROL   WPAR1+1    ; {2C1B} APPLY CARRY, MUL HIGH BY 2
         ASL   WPAR1      ; {2C1B} MUL LOW BYTE BY 2
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE IN .A
         ROL              ; {2C1B} APPLY CARRY AND MUL BY 2
         TAX              ; {2C1B} HOLD HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} HOLD LOW BYTE IN .A
         <<<
*


THE M16BY9 MACRO

SUMMARY

Condition Value
Name M16BY9
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 9
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 62
Bytes 36
Notes None
See Also D8BY9 M8BY9

DETAILS

The MUL16BY9 macro multiplies a given 16-bit number by nine.

LISTING 4.48: M16BY9 Macro Source

*
*``````````````````````````````*
* MBY9          (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* NINE.                        *
*                              *
* FORMULA: 9X = 8X + X         *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 62                   *
* SIZE: 36 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY9     MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MUL BY 2
         STA   WPAR1+1    ; {3C2B} STORE ON ZP
         ASL   WPAR1      ; {5C2B} MUL LOW BYTE BY 2
         ROL   WPAR1+1    ; {5C2B} CARRY AND MUL HIGH BY 2
         ASL   WPAR1      ; {5C2B} MUL LOW BY 2
         ROL   WPAR1+1    ; {5C2B} CARRY AND MUL HIGH BY 2
         LDA   WPAR1      ; {3C2B} LOAD LOW BYTE
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]1         ; {4C3B} ADD ORIGINAL VALUE
         STA   WPAR1      ; {3C2B} STORE ON ZP
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE
         ADC   ]1+1       ; {4C3B} ADD ORIGINAL HIGH BYTE
         TAX              ; {2C1B} HOLD FINAL HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} HOLD FINAL LOW BYTE IN .A
         <<<
*


THE M16BY10 MACRO

SUMMARY

Condition Value
Name M16BY10
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 10
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 66
Bytes 39
Notes None
See Also D8BY10 M8BY10

DETAILS

The MUL16BY10 macro multiplies a given 16-bit number by ten.

LISTING 4.49: M16BY10 Macro Source

*
*``````````````````````````````*
* MBY10         (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* TEN.                         *
*                              *
* FORMULA: 10X = 2(4X + X)     *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 65                   *
* SIZE: 39 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY10    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER LOW BYTE
         ASL              ; {2C1B} MUL LOW BYTE BY 2
         STA   WPAR1      ; {3C2B} STORE ON ZERO PAGE
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} APPLY CARRY AND MUL BY 2
         STA   WPAR1+1    ; {3C2B} STORE ON ZERO PAGE
         ASL   WPAR1      ; {5C2B} MUL LOW BY 2
         ROL   WPAR1+1    ; {5C2B} CARRY AND MUL HIGH BY 2
         LDA   ]1         ; {4C3B} LOAD ORIGINAL LOW BYTE
         CLC              ; {2C1B} CLEAR CARRY
         ADC   WPAR1      ; {3C2B} ADD ZP LOW BYTE
         STA   WPAR1      ; {3C2B} STORE BACK ON ZP
         LDA   ]1+1       ; {4C3B} LOAD ORIGINAL HIGH BYTE
         ADC   WPAR1+1    ; {3C2B} ADD ZP HIGH BYTE
         STA   WPAR1+1    ; {3C2B} STORE BACK ON ZP
         ASL   WPAR1      ; {5C2B} MULTIPLY NEW VAL LOW BY 2
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE IN .A
         ROL              ; {2C1B} CARRY AND MUL HIGH BY 2
         TAX              ; {2C1B} HOLD FINAL HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} HOLD FINAL LOW BYTE IN .A
         <<<
*


THE M16BY1H MACRO

SUMMARY

Condition Value
Name M16BY100
Type Macro
File MAC.M8BY.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply a 16-bit value by 100
Input ]1 = Number to multiply
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 124
Bytes 70
Notes None
See Also none

DETAILS

The MUL16BY1H macro multiplies a given 16-bit number by one hundred.

LISTING 4.50: M16BY1H Macro Source

*
*``````````````````````````````*
* MBY1H         (NATHAN RIGGS) *
*                              *
* MULTIPLY A 16-BIT NUMBER BY  *
* ONE HUNDRED.                 *
*                              *
* FORMULA: 100X = 4(16X+8X+X)  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = NUMBER ADDRESS         *
*                              *
* CYCLES: 124                  *
* SIZE: 70 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MBY1H    MAC
         LDA   ]1         ; {4C3B} LOAD NUMBER INTO .A
         ASL              ; {2C1B} MUL LOW BYTE BY 2
         STA   WPAR2      ; {3C2B} STORE IN ZP LOC 1
         LDA   ]1+1       ; {4C3B} LOAD NUMBER HIGH BYTE
         ROL              ; {2C1B} CARRY AND MUL BY 2
         STA   WPAR2+1    ; {3C2B} STORE IN ZP LOC 1
         ASL   WPAR2      ; {5C2B} MUL ZP LOW BYTE BY 2
         ROL   WPAR2+1    ; {5C2B} CARRY AND MUL ZP HIGH BY 2
         ASL   WPAR2      ; {5C2B} MUL LOW BY 2
         ROL   WPAR2+1    ; {5C2B} MUL HIGH BY 2
         LDA   WPAR2      ; {3C2B} LOAD LOW BYTE IN .A
         ASL              ; {2C1B} MULTIPLY BY TWO
         STA   WPAR1      ; {3C2B} STORE IN 2ND ZP LOC
         LDA   WPAR2+1    ; {3C2B} LOAD HIGH BYTE IN .A
         ROL              ; {2C1B} CARRY AND MUL BY 2
         STA   WPAR1+1    ; {3C2B} STORE IN 2ND ZP LOC
         LDA   ]1         ; {4C3B} LOAD ORIGINAL VALUE
         CLC              ; {2C1B} CLEAR CARRY
         ADC   WPAR1      ; {3C2B} ADD LOW BYTE ZP LOC 1
         STA   WPAR1      ; {3C2B} STORE AT ZP LOC 1
         LDA   ]1+1       ; {4C3B} LOAD ORIGINAL HIGH BYTE
         ADC   WPAR1+1    ; {3C2B} ADD ZP LOC HIGH
         STA   WPAR1+1    ; {3C2B} STORE BACK AT ZP LOC 1 HIGH
         LDA   WPAR1      ; {3C2B} LOAD LOC 1 LOW BYTE IN .A
         CLC              ; {2C1B} CLEAR CARRY
         ADC   WPAR2      ; {3C2B} ADD 2ND ZP LOC LOW BYTE
         STA   WPAR1      ; {3C2B} STORE IN LOC 1 LOW
         LDA   WPAR1+1    ; {3C2B} LOAD ZP LOC 1 HIGH BYTE
         ADC   WPAR2+1    ; {3C2B} ADD 2ND LOC HIGH BYTE
         STA   WPAR1+1    ; {3C2B} STORE BACK IN ZP LOC 1 HIGH
         ASL   WPAR1      ; {5C2B} MULTIPLY THAT VALUE LOW BY 2
         ROL   WPAR1+1    ; {5C2B} CARRY AND MUL HIGH BY 2
         LDA   WPAR1      ; {3C2B} LOAD LOW BYTE IN .A
         ASL              ; {2C1B} MULTIPLY AGAIN BY TWO
         STA   WPAR1      ; {3C2B} STORE IN ZP LOC 1 LOW
         LDA   WPAR1+1    ; {3C2B} LOAD HIGH BYTE IN .A
         ROL              ; {2C1B} CARRY AND MUL HIGH BY 2
         TAX              ; {2C1B} HOLD FINAL HIGH BYTE IN .X
         LDA   WPAR1      ; {3C2B} HOLD FINAL LOW BYTE IN .A
         <<<
*

General Purpose Math: 8-bit Procedures

These macros are dedicated to adding, subtracting, multiplying or dividing a given 8-bit number by another arbitrary 8-bit number. All values are unsigned; wrappers for signed numbers will be provided in a future revision, along with a modulus macro that wraps around DIV8.

LISTING 4.60: MAC.MATHBAS.ASM Header Source

*
*``````````````````````````````*
* MAC.MATH8.ASM                *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      01-APR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* SUBROUTINE FILES USED        *
*                              *
* SUB.DIVDU8                   *
* SUB.MULTU8                   *
*                              *
* LIST OF MACROS               *
*                              *
* ADD8  : ADD 8BIT NUMBERS     *
* SUB8  : SUBTRACT 8BIT NUMS   *
* MUL8  : MULTIPLY 8BIT NUMS   *
* DIV8  : DIVIDE 8BIT NUMS     *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE ADD8 MACRO

SUMMARY

Condition Value
Name ADD8
Type Macro
File MAC.MATH8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Add one 8-bit number to another
Input ]1 = first number to add
]2 = second number to add
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 21
Bytes 15
Notes None
See Also SUB8 ADD16

DETAILS

The ADD8 macro adds two arbitrary 8-bit numbers and passes back the sum in the .A register and in RETURN. Note that this macro, along with SUB8, is included as a courtesy to beginners, and they should not be relied on for fast and compact code (bytes and cycles are wasted to keep within the standards of the library).

LISTING 4.61: ADD8 Macro Source

*
*``````````````````````````````*
* ADD8          (NATHAN RIGGS) *
*                              *
* DIRTY MACRO TO ADD TWO BYTES *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = ADDEND 1               *
*  ]2 = ADDEND 2               *
*                              *
* CYCLES: 21                   *
* SIZE: 15 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
ADD8     MAC
         LDA   #1         ; {3C2B}
         STA   RETLEN     ; {4C3B}
         LDA   ]1         ; {4C3B}
         CLC              ; {2C1B}
         ADC   ]2         ; {4C3B}
         STA   RETURN     ; {4C3B}
         <<<
*


THE SUB8 MACRO

SUMMARY

Condition Value
Name SUB8
Type Macro
File MAC.MATH8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Add one 8-bit number to another
Input ]1 = Minuend
]2 = Subtrahend
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 21
Bytes 15
Notes None
See Also ADD8 SUB16

DETAILS

The SUB8 macro subtracts one arbitrary 8-bit number from another and passes back the sum in the .A register and in RETURN. Note that this macro, like with ADD8, is included as a courtesy to beginners, and should not be relied on for fast and compact code (bytes and cycles are wasted to keep within the standards of the library).

LISTING 4.62: SUB8 Macro Source

*
*``````````````````````````````*
* SUB8          (NATHAN RIGGS) *
*                              *
* MACRO TO SUBTRACT TWO BYTES  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = MINUEND                *
*  ]2 = SUBTRAHEND             *
*                              *
* CYCLES: 21                   *
* SIZE: 15 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
SUB8     MAC
         LDA   #1         ; {3C2B}
         STA   RETLEN     ; {4C3B}
         LDA   ]1         ; {4C3B}
         SEC              ; {2C1B}
         SBC   ]2         ; {4C3B}
         STA   RETURN     ; {4C3B}
         <<<
*


THE MUL8 MACRO

SUMMARY

Condition Value
Name MUL8
Type Macro
File MAC.MATH8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply one 8-bit number by another
Input ]1 = Multiplicand
]2 = Multiplier
Output none
Dependencies SUB.MULTU8
Flags Destroyed NZCV
Cycles 97+
Bytes 56
Notes None
See Also DIV8 MUL16

DETAILS

The MUL8 macro multiplies one 8-bit number by another, passing back the 16-bit product in RETURN and in the .A (low byte) and .X (high byte) registers.

LISTING 4.63: MUL8 Macro Source

*
*``````````````````````````````*
* MUL8          (NATHAN RIGGS) *
*                              *
* MULTIPLIES TWO 8BIT VALUES   *
* AND RETURNS A 16BIT RESULT   *
* IN .A,.X (LOW, HIGH).        *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = MULTIPLICAND           *
*  ]2 = MULTIPLIER             *
*                              *
* CYCLES: 97+                  *
* BYTES: 56 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MUL8     MAC
         LDA   ]1         ; {4C3B}
         LDX   ]2         ; {4C3B}
         JSR   MULTU8     ; {89C50B}
         <<<
*


THE MULTU8 SUBROUTINE

SUMMARY

Condition Value
Name MULTU8
Type Subroutine
File SUB.MULTU8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply one 8-bit number by another
Input WPAR1 = Multiplicand
WPAR2 = Multiplier
Output none
Dependencies SUB.MULTU8
Flags Destroyed NZCV
Cycles 83+
Bytes 47
Notes None
See Also MUL16

DETAILS

The MUL8 macro multiplies one 8-bit number by another, passing back the 16-bit product in RETURN and in the .A (low byte) and .X (high byte) registers (RETLEN holds 2, the length in bytes of the return value).

LISTING 4.63: MULTU8 Subroutine Source

*
*``````````````````````````````*
* MULTU8        (NATHAN RIGGS) *
*                              *
* MULTIPLY TWO 8-BIT NUMBERS.  *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = MULTIPLIER          *
*  WPAR2 = MULTIPLICAND        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 83+                  *
* SIZE: 47 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]MUL1    EQU   WPAR1      ; MULTIPLIER
]MUL2    EQU   WPAR2      ; MULTIPLICAND
*
MULTU8
         STA   ]MUL1      ; {3C2B}
         STX   ]MUL2      ; {3C2B}
         LDA   #0         ; {3C2B} CLEAR REGISTERS
         TAY              ; {2C1B}
         TAX              ; {2C1B}
         STA   ]MUL1+1    ; {3C2B} CLEAR HIBYTE
         BEQ   :GOLOOP    ; {3C2B}
:DOADD
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]MUL1      ; {3C2B} ADD MULTIPLIER
         TAX              ; {2C1B} HOLD IN .Y
         TYA              ; {2C1B} XFER .X TO .A
         ADC   ]MUL1+1    ; {3C2B} ADD MULTIPLIER HIBYTE
         TAY              ; {2C1B} HOLD BACK IN .X
         TXA              ; {2C1B} MOVE LOBYTE INTO .A
:LP
         ASL   ]MUL1      ; {5C2B} SHIFT LEFT
         ROL   ]MUL1+1    ; {5C2B} ROLL HIBYTE
:GOLOOP
         LSR   ]MUL2      ; {5C2B} SHIFT MULTIPLIER
         BCS   :DOADD     ; {3C2B} IF SHIFTED IN CARRY ADD AGAIN
         BNE   :LP        ; {3C2B} OTHERWISE, LOOP
         LDA   #2         ; {3C2B} 16-BIT LENGTH, 2 BYTES
         STA   RETLEN     ; {4C3B} FOR RETURN LENGTH
         STX   RETURN     ; {4C3B} STORE LOBYTE
         STY   RETURN+1   ; {4C3B} STORE HIBYTE
         TXA              ; {2C1B} LOBYTE TO .A
         LDX   RETURN+1   ; {4C3B} HIBYTE TO .X
         RTS              ; {6C1B}


THE DIV8 MACRO

SUMMARY

Condition Value
Name DIV8
Type Macro
File MAC.MATH8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide one 8-bit number by another
Input ]1 = Dividend
]2 = Divisor
Output none
Dependencies SUB.DIVDU8
Flags Destroyed NZCV
Cycles 75+
Bytes 43
Notes None
See Also DIV8 DIVDU8

DETAILS

The DIV8 macro divides one 8-bit number by another, passing back the 8-bit result in RETURN and in the .A register.

LISTING 4.65: DIV8 Macro Source

*
*``````````````````````````````*
* DIV8          (NATHAN RIGGS) *
*                              *
* DIVIDES ONE 8BIT NUMBER BY   *
* ANOTHER AND STORES THE       *
* QUOTIENT IN .A WITH THE      *
* REMAINDER IN .X.             *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = DIVIDEND               *
*  ]2 = DIVISOR                *
*                              *
* CYCLES: 75+                  *
* SIZE: 43 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
DIV8     MAC
         LDA   ]1         ; {4C3B}
         LDX   ]2         ; {4C3B}
         JSR   DIVDU8     ; {67C37B}
         <<<
*


THE DIVDU8 SUBROUTINE

SUMMARY

Condition Value
Name DIVDU8
Type Subroutine
File SUB.DIVDU8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide one 8-bit number by another
Input WPAR1 = Dividend
WPAR2 = Divisor
Output none
Dependencies SUB.DIVDU8
Flags Destroyed NZCV
Cycles 61+
Bytes 34
Notes None
See Also DIV16

DETAILS

The DIVDU8 subroutine divides an 8-bit dividend by an 8-bit divisor, passing back an 8-bit result in the .A register and RETURN. Additionally, any remainder is returned in the .X register.

LISTING 4.63: SUB8 Macro Source

*
*``````````````````````````````*
* DIVDU8        (NATHAN RIGGS) *
*                              *
* DIVIDE WITH TWO 8-BIT VALUES *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = DIVIDEND            *
*  WPAR2 = DIVISOR             *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 61+                  *
* SIZE: 34 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]DVEND   EQU   WPAR1      ; DIVIDEND
]DVSOR   EQU   WPAR2      ; DIVISOR
*
DIVDU8
         STX   ]DVEND     ; {3C2B} .X HOLDS DIVIDEND
         STA   ]DVSOR     ; {3C2B} .A HOLDS DIVISOR
         LDA   #$00       ; {3C2B} CLEAR ACCUMULATOR
         LDX   #8         ; {3C2B} COUNTER
         ASL   ]DVSOR     ; {5C2B} SHIFT LEFT DIVISOR
:L1      ROL              ; {2C1B} ROTATE LEFT .A
         CMP   ]DVEND     ; {3C2B} COMPARE TO DIVIDEND
         BCC   :L2        ; {3C2B} IF NEXT BIT = 0, BRANCH :L2
         SBC   ]DVEND     ; {3C2B} OTHERWISE, SUBTRACT DIVIDEND
:L2      ROL   ]DVSOR     ; {5C2B} LEFT DIVISOR
         DEX              ; {2C1B} DECREMENT COUNTER
         BNE   :L1        ; {3C2B} IF > 0, LOOP
         TAX              ; {2C1B} REMAINDER IN .X
         LDA   #1         ; {3C2B}
         STA   RETLEN     ; {4C3B}
         LDA   ]DVSOR     ; {3C2B} RESULT IN .A
         STA   RETURN     ; {4C3B}
         RTS              ; {6C1B}


General Purpose Math: 16-bit Procedures

These macros are dedicated to adding, subtracting, multiplying or dividing with two 8-bit or 16-bit numbers, as well as a macro for 16-bit comparisons. All values are unsigned; wrappers for signed numbers will be provided in a future revision, along with a modulus macro that wraps around DIV16.

While these macros and subroutines are adequate for most general purposes, if speed or size is a major concern then it is advised that at least addition and subtraction be done manually, as some bytes and cycles are "wasted" keeping the library's operating principles intact.

LISTING 4.70: MAC.MATHBAS.ASM Header Source

*
*``````````````````````````````*
* MAC.MATH16.ASM               *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      01-APR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* SUBROUTINE FILES USED        *
*                              *
* SUB.ADDIT16                  *
* SUB.COMP16                   *
* SUB.DIVDU16                  *
* SUB.MULTU16                  *
* SUB.SUBT16                   *
*                              *
* LIST OF MACROS               *
*                              *
* ADD16 : ADD 16BIT NUMBERS    *
* SUB16 : SUBTRACT 16BIT NUMS  *
* MUL16 : MULTIPLY 16BIT NUMS  *
* DIV16 : DIVIDE 16BIT NUMS    *
* CMP16 : COMPARE 16BIT NUMS   *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE ADD16 MACRO

SUMMARY

Condition Value
Name ADD16
Type Macro
File MAC.MATH16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Add two 16-bit numbers
Input ]1 = First Addend
]2 = Second Addend
Output none
Dependencies SUB.ADDIT16
Flags Destroyed NZCV
Cycles 78+
Bytes 51
Notes None
See Also ADD8 ADDIT16

DETAILS

The ADD16 macro adds two 16-bit numbers, passing back the 16-bit result in RETURN and in the .A (low byte) and .X (high byte) registers.

LISTING 4.71: ADD16 Macro Source

*
*``````````````````````````````*
* ADD16         (NATHAN RIGGS) *
*                              *
* ADD TWO 16BIT VALUES, STORE  *
* RESULT IN .A, .X (LOW, HIGH) *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = ADDEND 1               *
*  ]2 = ADDEND 2               *
*                              *
* CYCLES: 78+                  *
* SIZE: 51 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
ADD16    MAC
         _MLIT ]1;WPAR1   ; {16C12B}
         _MLIT ]2;WPAR2   ; {16C12B}
         JSR   ADDIT16    ; {46C27B}
         <<<
*


THE ADDIT16 SUBROUTINE

SUMMARY

Condition Value
Name ADDIT16
Type Subroutine
File SUB.ADDIT16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Add two 16-bit numbers
Input WPAR1 = Augend
WPAR2 = Addend
Output none
Dependencies SUB.ADDIT16
Flags Destroyed NZCV
Cycles 40+
Bytes 24
Notes None
See Also ADD16

DETAILS

The ADDIT16 subroutine adds two 16-bit numbers and passes back a 16-bit sum via RETURN and the .A (low byte) and .X (high byte) registers. RETLEN holds #2, the byte-length of the return value.

LISTING 4.72: ADDIT16 Macro Source

*
*``````````````````````````````*
* ADDIT16       (NATHAN RIGGS) *
*                              *
* ADD TWO 16-BIT VALUES.       *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = AUGEND              *
*  WPAR2 = ADDEND              *
*                              *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 40                   *
* SIZE: 24 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]ADD1    EQU   WPAR1      ; FIRST ARGUMENT
]ADD2    EQU   WPAR2      ; SECOND ARGUMENT
*
ADDIT16
         LDA   #2         ; {2C2B} PUT SUMMAND LENGTH
         STA   RETLEN     ; {4C3B} IN RETLEN
         LDA   ]ADD1      ; {3C2B} ADD LOBYTES
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]ADD2      ; {3C2B}
         TAY              ; {2C1B} TEMPORARY STORE IN .Y
         LDA   ]ADD1+1    ; {3C2B} ADD HIBYTES
         ADC   ]ADD2+1    ; {3C2B}
         TAX              ; {2C1B} STORE IN .X
         TYA              ; {2C1B} XFER LOBYTE TO .A
         STA   RETURN     ; {4C3B} ALSO PASS BACK IN RETURN
         STX   RETURN+1   ; {4C3B} TO KEEP CONSISTENT
         RTS              ; {6C1B}


THE SUB16 MACRO

SUMMARY

Condition Value
Name SUB16
Type Macro
File MAC.MATH16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Subtract a 16-bit number from another
Input ]1 = Minuend
]2 = Subtrahend
Output none
Dependencies SUB.SUBT16
Flags Destroyed NZCV
Cycles 79+
Bytes 51
Notes None
See Also SUB8 SUBT16

DETAILS

The SUB16 macro subtracts one 16-bit number from another, storing the difference in RETURN an in the .A (low byte) and .X (high byte) registers. The byte length of the difference, two, is stored in RETLEN.

LISTING 4.73: SUB16 Macro Source

*
*``````````````````````````````*
* SUB16         (NATHAN RIGGS) *
*                              *
* SUBTRACTS ONE 16BIT INTEGER  *
* FROM ANOTHER, STORING THE    *
* RESULT IN .A, .X (LOW, HIGH) *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = MINUEND                *
*  ]2 = SUBTRAHEND             *
*                              *
* CYCLES: 79+                  *
* SIZE: 51 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
SUB16    MAC
         _MLIT ]1;WPAR1   ; {16C12B}
         _MLIT ]2;WPAR2   ; {16C12B}
         JSR   SUBT16     ; {47C27B}
         <<<
*


THE SUBT16 SUBROUTINE

SUMMARY

Condition Value
Name SUBT16
Type Subroutine
File SUB.SUBT16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose subtract one 16-bit number from another
Input WPAR1 = Minuend
WPAR2 = Subtrahend
Output none
Dependencies SUB.SUBT16
Flags Destroyed NZCV
Cycles 41+
Bytes 24
Notes None
See Also SUB16

DETAILS

The SUBT16 subroutine subtracts one 16-bit number from another, storing the difference in RETURN as well as in the .A (low byte) and .X registers (high byte). The byte-length of the return value, two, is held in RETLEN.

LISTING 4.74: ADDIT16 Macro Source

*
*``````````````````````````````*
* SUBT16        (NATHAN RIGGS) *
*                              *
* SUBTRACT A 16-BIT SUBTRAHEND *
* FROM A MINUEND.              *
*                              *
* INPUT                        *
*                              *
*  WPAR1 = MINUEND             *
*  WPAR2 = SUBTRAHEND          *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 41+                  *
* SIZE: 24 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]MINU    EQU   WPAR1      ; MINUEND
]SUBT    EQU   WPAR2      ; SUBTRAHEND
*
SUBT16
         LDA   #2         ; {3C2B}
         STA   RETLEN     ; {4C3B}
         LDA   ]MINU      ; {3C2B} SUBTRACT SUBTRAHEND
         SEC              ; {2C1B} LOBYTE FROM MINUEND
         SBC   ]SUBT      ; {3C2B} LOBYTE
         TAY              ; {2C1B} HOLD LOBYTE IN .Y
         LDA   ]MINU+1    ; {3C2B} SUBTRACT SUBTRAHEND
         SBC   ]SUBT+1    ; {3C2B} HIBYTE FROM MINUEND
         TAX              ; {2C1B} HIGH BYTE, PASS IN .X
         TYA              ; {2C1B} LOBYTE BACK IN .A
         STA   RETURN     ; {4C3B}
         STX   RETURN+1   ; {4C3B}
         RTS              ; {6C1B}


THE MUL16 MACRO

SUMMARY

Condition Value
Name SUB16
Type Macro
File MAC.MATH16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply two 16-bit numbers
Input ]1 = Multiplier
]2 = Multiplicand
Output none
Dependencies SUB.MULTU16
Flags Destroyed NZCV
Cycles 144+
Bytes 91
Notes None
See Also MUL8 MULT16

DETAILS

The MUL16 macro multiplies two 16-bit values, holding the product in RETURN with a total byte-length of 4 in RETLEN (32-bit product). If the full 32 bits is not needed, the lower 16-bits of the product are held in the .A register (low byte) and the .X register (high byte).

LISTING 4.75: MUL16 Macro Source

*
*``````````````````````````````*
* MUL16         (NATHAN RIGGS) *
*                              *
* MULTIPLIES TWO 16BIT NUMBERS *
* AND RETURNS THE PRODUCT IN   *
*.A, .X (LOW, HIGH).           *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = MULTIPLICAND           *
*  ]2 = MULTIPLIER             *
*                              *
* CYCLES: 144+                 *
* SIZE: 91 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
MUL16    MAC
         _MLIT ]1;WPAR1   ; {16C12B}
         _MLIT ]2;WPAR2   ; {16C12B}
         JSR   MULTU16    ; {112C67B}
         <<<
*


THE MULTU16 SUBROUTINE

SUMMARY

Condition Value
Name MULTU16
Type Subroutine
File SUB.MULTU16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Multiply two 16-bit numbers
Input WPAR1 = Multiplier
WPAR2 = Multiplicand
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 106+
Bytes 64
Notes None
See Also MUL16

DETAILS

The MULTu16 subroutine accepts two 16-bit values and multiplies them, passing back the 32-bit product via RETURN, with RETLEN holding its byte-length, four. Additionally, the bottom two bytes of the product are held in the .A (low byte) and .X (high byte) registers for faster retrieval if the number is known to be 16 bits.

LISTING 4.76: MULTU16 Subroutine Source

*
*``````````````````````````````*
* MULT16        (NATHAN RIGGS) *
*                              *
* MULTIPLY TWO 16-BIT VALUES.  *
* NOTE THAT THIS ONLY WORKS    *
* CORRECTLY WITH UNSIGNED      *
* VALUES. SIGNS MUST BE        *
* DETERMINED BEFOREHAND.       *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = MULTIPLICAND        *
*  WPAR2 = MULTIPLIER          *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 106+                 *
* SIZE: 64 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]MCAND   EQU   WPAR1      ; MULTIPLICAND
]MLIER   EQU   WPAR2      ; MULTIPLIER
]HPROD   EQU   WPAR3      ; HIGH BYTES OF PRODUCT
*
MULTU16
         LDA   #0         ; {3C2B} ZERO OUT TOP TWO
         STA   ]HPROD     ; {4C3B} HIGH BYTES OF 32-BIT
         STA   ]HPROD+1   ; {4C3B} RESULT
         LDX   #17        ; {4C3B} # OF BITS IN MLIER PLUS 1
                          ; FOR LAST CARRY INTO PRODUCT
         CLC              ; {2C1B} CLEAR CARRY FOR 1ST TIME
                          ; THROUGH LOOP.
:MLP
*
** IF NEXT BIT = 1, HPROD += 1
*
         ROR   ]HPROD+1   ; {5C2B} SHIFT HIGHEST BYTE
         ROR   ]HPROD     ; {5C2B} SHIFT 2ND-HIGHEST
         ROR   ]MLIER+1   ; {5C2B} SHIFT 3RD-HIGHEST
         ROR   ]MLIER     ; {5C2B} SHIFT LOW BYTE
         BCC   :DX        ; {3C2B} BRANCH IF NEXT BIT = 0
         CLC              ; {2C1B} OTHERWISE NEXT BIT =1,
         LDA   ]MCAND     ; {3C2B} SO ADD MCAND TO PRODUCT
         ADC   ]HPROD     ; {3C2B}
         STA   ]HPROD     ; {3C2B} STORE NEW LOBYTE
         LDA   ]MCAND+1   ; {3C2B}
         ADC   ]HPROD+1   ; {3C2B}
         STA   ]HPROD+1   ; {3C2B} STORE NEW HIBYTE
:DX
         DEX              ; {2C1B} DECREASE COUNTER
         BNE   :MLP       ; {3C2B} DO MUL LOOP UNTIL .X = 0
*
** NOW STORE IN RETURN, WITH LOWEST TWO
** BYTES ALSO LEFT IN .A (LO) AND .X (HI)
*
         LDA   #4         ; {3C2B} LENGTH OF PRODUCT
         STA   RETLEN     ; {4C3B} STORED IN RETLEN
         LDA   ]HPROD+1   ; {3C2B}
         STA   RETURN+3   ; {4C3B}
         LDA   ]HPROD     ; {3C2B}
         STA   RETURN+2   ; {4C3B}
         LDX   ]MLIER+1   ; {3C2B}
         STX   RETURN+1   ; {4C3B}
         LDA   ]MLIER     ; {3C2B}
         STA   RETURN     ; {4C3B}
         RTS              ; {6C1B}


THE DIV16 MACRO

SUMMARY

Condition Value
Name DIV16
Type Macro
File MAC.MATH16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide one 16-bit number by another
Input ]1 = Dividend
]2 = Divisor
Output none
Dependencies SUB.DIVDU16
Flags Destroyed NZCV
Cycles 133+
Bytes 81
Notes None
See Also DIV8 DIVDU16

DETAILS

The DIV16 macro divides one 16-bit number by another, storing the 16-bit result in both RETURN and in the .A (low byte) and .X (high) registers. Additionally, any possible remainder is passed back via the .Y register. RETLEN holds the value 2, which represents the byte-length of the result.

Note that no considerations are given for signed numbers in this subroutine. If necessary, a macro wrapper for signed values will be provided in future updates.

LISTING 4.77: DIV16 Macro Source

*
*``````````````````````````````*
* DIV16         (NATHAN RIGGS) *
*                              *
* DIVIDES ONE 16BIT NUMBER BY  *
* ANOTHER AND RETURNS THE      *
* RESULT IN .A, .X (LOW,HIGH). *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = DIVIDEND               *
*  ]2 = DIVISOR                *
*                              *
* CYCLES: 133+                 *
* SIZE: 81 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
DIV16    MAC
         _MLIT ]1;WPAR1   ; {16C12B}
         _MLIT ]2;WPAR2   ; {16C12B}
         JSR   DIVDU16    ; {101C57B} UNSIGNED
         FIN
         <<<
*


THE DIVDU16 SUBROUTINE

SUMMARY

Condition Value
Name DIVDU16
Type Subroutine
File SUB.DIVDU16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Divide one 16-bit number by another
Input WPAR1 = Dividend
WPAR2 = Divisor
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 95+
Bytes 54
Notes None
See Also DIV16

DETAILS

The MULTu16 subroutine accepts two 16-bit values and multiplies them, passing back the 32-bit product via RETURN, with RETLEN holding its byte-length, four. Additionally, the bottom two bytes of the product are held in the .A (low byte) and .X (high byte) registers for faster retrieval if the number is known to be 16 bits.

LISTING 4.78: DIVDU16 Subroutine Source

*
*``````````````````````````````*
* DIVDU16       (NATHAN RIGGS) *
*                              *
* DIVIDE WITH 16-BIT VALUES.   *
*                              *
* ADAPTED FROM LISTINGS IN THE *
* C=64 MAGAZINES.              *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = DIVIDEND            *
*  WPAR2 = DIVISOR             *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 95+                  *
* SIZE: 54 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]DVEND   EQU   WPAR1      ; DIVIDEND
]DVSOR   EQU   WPAR2      ; DIVISOR
]REM     EQU   WPAR3      ; REMAINDER
]RESULT  EQU   WPAR1      ; DIVISION RESULT
*
DIVDU16
         LDA   #0         ; {4C3B} RESET REMAINDER
         STA   ]REM       ; {3C2B}
         STA   ]REM+1     ; {3C2B}
         LDX   #16        ; {3C2B} NUMBER OF BITS
:DVLP
         ASL   ]DVEND     ; {5C2B} LOBYTE * 2
         ROL   ]DVEND+1   ; {5C2B} HIBYTE * 2
         ROL   ]REM       ; {5C2B} LOBYTE * 2
         ROL   ]REM+1     ; {5C2B} HIBYTE * 2
         LDA   ]REM       ; {3C2B}
         SEC              ; {2C1B} SET CARRY
         SBC   ]DVSOR     ; {3C2B} SUBTRACT DIVISOR
         TAY              ; {2C1B} TO SEE IF IT FITS IN DVEND,
         LDA   ]REM+1     ; {3C2B} HOLD LOBYTE IN .Y
         SBC   ]DVSOR+1   ; {3C2B} AND DO SAME WITH HIBYTES
         BCC   :SKIP      ; {3C2B} IF C=0, DVSOR DOESN'T FIT
*
         STA   ]REM+1     ; {3C2B} ELSE SAVE RESULT AS REM
         STY   ]REM       ; {3C2B}
         INC   ]RESULT    ; {5C2B} AND INC RES
:SKIP
         DEX              ; {2C1B} DECREASE BIT COUNTER
         BNE   :DVLP      ; {3C2B} RELOOP IF > 0
         LDA   #2         ; {3C2B} LENGTH OF RESULT IN BYTES
         STA   RETLEN     ; {4C3B} STORED IN RETLEN
         LDA   ]RESULT    ; {3C2B} STORE RESULT LOBYTE
         STA   RETURN     ; {4C3B} IN .A AND RETURN
         LDX   ]RESULT+1  ; {3C2B} STORE HIBYTE IN .X
         STX   RETURN+1   ; {4C3B} AND IN RETURN+1
         RTS              ; {6C1B}


THE CMP16 MACRO

SUMMARY

Condition Value
Name CMP16
Type Macro
File MAC.MATH16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Compare two 16-bit numbers
Input ]1 = First comparison argument
]2 = Second comparison argument
Output none
Dependencies SUB.COMP16
Flags Destroyed NZCV
Cycles 100+
Bytes 53
Notes None
See Also COMP16

DETAILS

The CMP16 macro mimics the CMP instruction, except that it compares 16-bit values instead of the regular 8-bit values. The macro accepts two parameters, then sets the status flags based on the results of a comparison between the values. The status flags are set as such:

  • If the values are equal, then the Zero flag is set to 1

  • If the first value is greater than the second, then the Carry flag is set to zero

  • If the first value is less than or equal to the second, then the Carry flag is set to 1

  • If a signed first value is greater than a signed second value, then the Negative flag is set to 0

  • If a signed first value is less than or equal to the second, the the Negative flag is set to 1

LISTING 4.79: CMP16 Macro Source

*
*``````````````````````````````*
* CMP16         (NATHAN RIGGS) *
*                              *
* COMPARES TWO 16BIT VALUES    *
* AND ALTERS THE P-REGISTER    *
* ACCORDINGLY (FLAGS).         *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = WORD 1 TO COMPARE      *
*  ]2 = WORD 2 TO COMPARE      *
*                              *
* CYCLES: 100+                 *
* SIZE: 53 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
CMP16    MAC
         _MLIT ]1;WPAR1   ; {16C12B}
         _MLIT ]2;WPAR2   ; {16C12B}
         JSR   COMP16     ; {59C29B}
         <<<


THE COMP16 SUBROUTINE

SUMMARY

Condition Value
Name COMP16
Type Subroutine
File SUB.COMP16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Compare one 16-bit value to another
Input WPAR1 = First comparison argument
WPAR2 = Second comparison argument
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 53+
Bytes 26
Notes None
See Also CMP16

DETAILS

The COMP16 subroutine compares one 16-bit value to another, much like the CMP instruction for 8-bit values. The flags are set given the following conditions:

  • If the values are equal, then the Zero flag is set to 1
  • If the first value is greater than the second, then the Carry flag is set to zero
  • If the first value is less than or equal to the second, then the Carry flag is set to 1
  • If a signed first value is greater than a signed second value, then the Negative flag is set to 0
  • If a signed first value is less than or equal to the second, the the Negative flag is set to 1

LISTING 4.80: COMP16 Subroutine Source

*
*``````````````````````````````*
* COMP16        (NATHAN RIGGS) *
*                              *
* 16-BIT COMPARISON DIRECTIVE  *
*                              *
* BASED ON LEVENTHAL AND       *
* SAVILLE'S /6502 ASSEMBLY     *
* LANGUAGE ROUTINES/ LISTING   *
*                              *
*  Z FLAG = 1 IF VALUES EQUAL  *
*  C FLAG = 0 IF CMP1 > CMP2,  *
*           1 IF CMP1 <= CMP2  *
*  N FLAG = 1 IF SIGNED CMP1 > *
*           SIGNED CMP2, 0 IF  *
*           SIGNED CMP1 <=     *
*           SIGNED CMP2        *
*                              *
* INPUT:                       *
*                              *
*  ]WPAR1 = 16-BIT CMP VALUE   *
*  ]WPAR2 = 16-BIT CMP VALUE   *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 53+                  *
* SIZE: 26 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]CMP1    EQU   WPAR1      ; COMPARISON VAR 1
]CMP2    EQU   WPAR2      ; COMPARISON VAR 2
*
COMP16
         LDA   ]CMP1      ; {3C2B} FIRST, COMPARE LOW BYTES
         CMP   ]CMP2      ; {3C2B}
         BEQ   :EQUAL     ; {3C2B} BRANCH IF EQUAL
         LDA   ]CMP1+1    ; {3C2B} COMPARE HIGH BYTES
         SBC   ]CMP2+1    ; {3C2B} SET ZERO FLAG TO 0,
         ORA   #1         ; {2C1B} SINCE LOW BYTES NOT EQUAL
         BVS   :OVFLOW    ; {3C2B} HANDLE V FLAG FOR SIGNED
         RTS              ; {6C1B}
:EQUAL
         LDA   ]CMP1+1    ; {3C2B} COMPARE HIGH BYTES
         SBC   ]CMP2+1    ; {3C2B}
         BVS   :OVFLOW    ; {3C2B} HANDLE OVERFLOW FOR SIGNED
         RTS              ; {6C1B}
:OVFLOW
         EOR   #$80       ; {3C2B} COMPLEMENT NEGATIVE FLAG
         ORA   #1         ; {3C2B} IF OVERFLOW, Z = 0
         RTS              ; {6C1B}


Pseudorandom Number Generation Macros and Subroutines

The final group of macros and subroutines in the math collection is dedicated to generating and managing pseudorandom numbers. The value of the number generated depends on an initial seed and a "magic number" that the seed is EOR'd by, and these are usually set before any pseudorandom number is generated. Additionally, these numbers are highly variable, but ultimately predictable if you know the seed, the EOR value, and the number of times a number is generated. This is useful for instances when a programmer wants definite and discrete results that are reproducible and seem planned but are simply based on the generation algorithm. The Atari game Pitfall, for instance, uses this exact method to determine the makeup of each screen of the game, saving valuable memory space while remaining regular enough to seem intentionally designed.

LISTING 4.90: MAC.MATHRND.ASM Header Source

*
*``````````````````````````````*
* MAC.MATHEXT.ASM              *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      03-APR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* SUBROUTINE FILES USED        *
*                              *
* SUB.RAND16.ASM               *
* SUB.RAND8.ASM                *
* SUB.RANDB.ASM                *
* SUB.PERCT16.ASM              *
* SUB.GCFCT16.ASM              *
* SUB.LCMUL16.ASM              *
*                              *
* LIST OF MACROS               *
*                              *
* RAND  : GET RANDOM BETWEEN   *
* RND16 : RANDOM WORD          *
* RND8  : RANDOM BYTE          *
* RNDMZ : RANDOMIZE            *
* RNDEOR: SET PRNG SEED + EOR  *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*


THE RNDEOR MACRO

SUMMARY

Condition Value
Name RNDEOR16
Type Macro
File MAC.MATHRND.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Set the seed and magic number for pseudorandom numbers
Input ]1 = Seed
]2 = EOR value
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 30+
Bytes 22
Notes None
See Also RNDMZ

DETAILS

The RNDEOR macro allows you to directly set both the seed and the magic number used by EOR in pseudorandom number generation. This is different from the RNDMZ in that the number you assign to the magic number becomes its actual value, rather than be used as an index in a lookup table.

LISTING 4.91: RNDEOR Macro Source

*
*``````````````````````````````*
* RNDEOR        (NATHAN RIGGS) *
*                              *
* DIRECTLY DETERMINE THE PRNG  *
* SEED AND EOR VALUES.         *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = SEED VALUE             *
*  ]2 = EOR MAGIC NUMBER VALUE *
*                              *
* CYCLES: 30+                  *
* SIZE: 22 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RNDEOR   MAC
         LDA   ]1         ; {4C3B}
         STA   RNDL       ; {3C2B}
         LDA   ]1+1       ; {4C3B}
         STA   RNDH       ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   ]MAGEOR    ; {4C3B}
         LDA   ]2+1       ; {4C3B}
         STA   ]MAGEOR+1  ; {4C3B}
         <<<
*


THE RNDMZ MACRO

SUMMARY

Condition Value
Name RNDMZ
Type Macro
File MAC.MATHRND.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Set the seed and magic number for pseudorandom numbers
Input ]1 = Seed
]2 = EOR value
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 56+
Bytes 35
Notes None
See Also RNDEOR

DETAILS

The RNDMZ macro first lets you set the seed value that initializes the pseudorandom number generator. Then, in the separate parameter, a byte value is passed that acts as the index for a table of 64 predetermined "magic numbers" (2 bytes long each) that are used for maximum variability in the generation of each number outputted. The second parameter is divided by four to ensure that it is a value between zero and 63, and then the magic number is picked from the following table of values (found in the math collection header file):

LISTING 3.91: Magic Number Table

002D0039003F005300BD00D7012F013D
014F015D019701A101AD01BF01C70215
02190225022F025D026D0285029102A1
02E5031D034B036903710387038D039F
03A303DD03F904290457046704830489
049104BF04C1053305470569058705C3
05DD05EB0641064B0653068B06C3076B
076D0779078307F1080D086108BF08D5

LISTING 4.92: RNDEOR Macro Source

*
*``````````````````````````````*
* RNDMZ         (NATHAN RIGGS) *
*                              *
* ASSIGN A SEED VALUE FOR THE  *
* PSEUDORANDOM NUMBER          *
* GENERATOR AS WELL AS AN EOR  *
* "MAGIC NUMBER." NO MATTER    *
* THE EOR VALUE PROVIDED, A    *
* VALUE WILL BE TAKEN FROM A   *
* TABLE THAT ALLOWS FOR A FULL *
* 65536 NON-REPEATED NUMBERS.  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = SEED VALUE             *
*  ]2 = EOR NUMBER REFERENCE   *
*                              *
* CYCLES: 56+                  *
* SIZE: 35 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RNDMZ    MAC
         LDA   ]1         ; {4C3B}
         STA   RNDL       ; {3C2B}
         LDA   ]1+1       ; {4C3B}
         STA   RNDH       ; {3C2B}
*
         LDA   ]2         ; {4C3B}
         LSR              ; {2C1B}
         LSR              ; {2C1B}
         TAY              ; {2C1B}
         LDA   #]MAGNUM   ; {3C2B}
         STA   ADDR1      ; {3C2B}
         LDA   #]MAGNUM/$100 ; {3C2B}
         STA   ADDR1+1    ; {3C2B}
         LDA   (ADDR1),Y  ; {5C2B}
         STA   ]MAGEOR    ; {4C3B}
         INY              ; {2C1B}
         LDA   (ADDR1),Y  ; {5C2B}
         STA   ]MAGEOR+1  ; {4C3B}
         <<<
*


THE RND8 MACRO

SUMMARY

Condition Value
Name RND8
Type Macro
File MAC.MATHRND.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate an 8-bit pseudorandom number
Input none
Output none
Dependencies RAND8
Flags Destroyed NZCV
Cycles 51+
Bytes 30
Notes None
See Also RAND8 RND16

DETAILS

The RND8 macro generates a pseudorandom number between 0 and 255. The number is passed back via the .A register as well as in RETURN.

LISTING 4.93: RND8 Macro Source

*
*``````````````````````````````*
* RND8          (NATHAN RIGGS) *
*                              *
* RETURN AN 8-BIT PSEUDORANDOM *
* NUMBER.                      *
*                              *
* PARAMETERS                   *
*                              *
*  NONE                        *
*                              *
* CYCLES: 51+                  *
* SIZE: 30 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RND8     MAC
         JSR   RAND8      ; {51C30B}
         <<<
*


THE RAND8 SUBROUTINE

SUMMARY

Condition Value
Name RAND8
Type Subroutine
File SUB.RAND8.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate an 8-bit pseudorandom number
Input none
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 45+
Bytes 27
Notes None
See Also RND8 RAND16

DETAILS

The RAND8 subroutine generates a pseudorandom number between 0 and 255.

LISTING 4.94: RND8 Subroutine Source

*
*``````````````````````````````*
* RAND8         (NATHAN RIGGS) *
*                              *
* GENERATE PSEUDO-RANDOM BYTE  *
*                              *
* INPUT:                       *
*                              *
*  NONE                        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 45+                  *
* SIZE: 27 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RAND8
         LDX   #8         ; {3C2B} NUMBER OF BITS
         LDA   RNDL+0     ; {3C2B} GET SEED
:A
         ASL              ; {2C1B} SHIFT THE REG
         ROL   RNDL+1     ; {5C2B} ROTATE HIGH BYTE
         BCC   :B         ; {3C2B} IF 1 BIT SHIFTED OUT,
         EOR   ]MAGEOR    ; {2C2B} APPLY XOR FEEDBACK
:B
         DEX              ; {2C1B} DECREASE BIT COUNTER
         BNE   :A         ; {3C2B} IF NOT ZERO, RELOOP
         STA   RNDL+0     ; {3C2B} STORE NEW SEED
         STA   RETURN     ; {4C3B} STORE IN RETURN
         LDY   #1         ; {3C2B} RETURN BYTE LENGTH
         STY   RETLEN     ; {4C3B} IN RETLEN
         CMP   #0         ; {2C2B} RELOAD FLAGS
         RTS              ; {6C1B}
*


THE RAND MACRO

SUMMARY

Condition Value
Name RAND
Type Macro
File MAC.MATHRND.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate an 8-bit pseudorandom number
between a given low and high value
Input ]1 = lower boundary
]2 = higher boundary
Output none
Dependencies RANDB
Flags Destroyed NZCV
Cycles 263+
Bytes 171
Notes None
See Also RND8 RND16 RANDB

DETAILS

The RAND macro takes a lower boundary and a higher boundary, both between 0 and 255, and generates a pseudo-random number between them. When possible, RND8 should be used due to the much higher number of cycles and bytes used in calculating the number between new boundaries.

LISTING 4.95: RAND Macro Source

*
*``````````````````````````````*
* RAND          (NATHAN RIGGS) *
*                              *
* RETURNS A RANDOM NUMBER IN   *
* REGISTER .A THAT IS BETWEEN  *
* THE LOW AND HIGH BOUNDARIES  *
* PASSED IN THE PARAMETERS.    *
*                              *
* NOTE THAT THIS RETURNS A     *
* BYTE, AND THUS ONLY DEALS    *
* WITH VALUES BETWEEN 0..255.  *
*                              *
* PARAMETERS                   *
*                              *
*  ]1 = LOW BOUNDARY           *
*  ]2 = HIGH BOUNDARY          *
*                              *
* CYCLES: 263+                 *
* SIZE: 171 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RAND     MAC
         LDA   ]1         ; {4C3B} LOW
         LDX   ]2         ; {4C3B} HIGH
         JSR   RANDB      ; {255C165B}
         <<<
*


THE RANDB SUBROUTINE

SUMMARY

Condition Value
Name RANDB
Type Subroutine
File SUB.RANDB.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate a pseudorandom number between a low and a high
Input BPAR1 = Lower boundary
BPAR2 = Upper boundary
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 249+
Bytes 162
Notes None
See Also RAND RND8

DETAILS

The RANDB subroutine generates a pseudorandom number between a given lower boundary and a high boundary. The number generated is stored in the .A register as well as in RETURN.

LISTING 4.96: RANDB Subroutine Source

*
*``````````````````````````````*
* RANDB         (NATHAN RIGGS) *
*                              *
* GET A RANDOM VALUE BETWEEN   *
* A MIN AND MAX 8-BIT BOUNDARY *
*                              *
* INPUT:                       *
*                              *
*  BPAR1 = MINIMUM VALUE       *
*  BPAR2 = MAXIMUM VALUE       *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 249+                 *
* SIZE: 162 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]NEWMIN  EQU   BPAR1      ; MINIMUM PARAMETER
]NEWMAX  EQU   BPAR2      ; MAXIMUM PARAMETER
]OLDMIN  EQU   WPAR1      ; OLD MINIMUM (1)
]OLDMAX  EQU   WPAR1+1    ; OLD MAXIMUM (255)
]OLDRNG  EQU   VARTAB     ; OLD RANGE
]NEWRNG  EQU   VARTAB+2   ; NEW RANGE
]MULRNG  EQU   VARTAB+4   ; MULTIPLIED RANGE
]DIVRNG  EQU   VARTAB+6   ; DIVIDED RANGE
]VALRNG  EQU   VARTAB+8   ; VALUE RANGE
]OLDVAL  EQU   VARTAB+10  ; OLD VALUE
]NEWVAL  EQU   VARTAB+12  ; NEW VALUE
]NUM1HI  EQU   VARTAB+14  ; MULTIPLICATION HI BYTE
]REMAIN  EQU   VARTAB+16  ; REMAINDER
*
RANDB
         STX   ]NEWMAX    ; {4C3B} NEW HIGH VALUE
         STA   ]NEWMIN    ; {4C3B} NEW LOW VALUE OF RANGE
*
** GET OLDMIN,OLDMAX,OLDVAL
*
         LDA   #1         ; {3C2B} OLD LOW IS ALWAYS 1
         STA   ]OLDMIN    ; {3C2B}
         LDA   #255       ; {3C2B} OLD HIGH IS ALWAYS 255
         STA   ]OLDMAX    ; {3C2B}
         LDX   #8         ; {3C2B} NUMBER OF BITS IN #
         LDA   RNDL+0     ; {3C2B} LOAD SEED VALUE
:AA
         ASL              ; {2C1B} SHIFT ACCUMULATOR
         ROL   RNDL+1     ; {5C2B}
         BCC   :BB        ; {3C2B} IF NEXT BIT IS 0, BRANCH
         EOR   ]MAGEOR    ; {2C2B} ELSE, APPLY XOR FEEDBACK
:BB
         DEX              ; {2C1B} DECREASE .X COUNTER
         BNE   :AA        ; {3C2B} IF > 0, KEEP LOOPING
         STA   RNDL+0     ; {3C2B} OVERWRITE SEED VALUE
         CMP   #0         ; {2C2B} RESET FLAGS
         STA   ]OLDVAL    ; {4C3B} STORE RANDOM NUMBER
*
** NEWVALUE = (((OLDVAL-NEWMIN) * (NEWMAX-NEWMIN) /
**            (OLDMAX-OLDMIN)) + NEWMIN
*
** OLDRANGE = (OLDMAX-OLDMIN)
** NEWRANGE = (NEWMAX - NEWMIN)
** NEWVAL = (((OLDVAL-OLDMIN) * NEWRANGE) / OLDRANGE) + NEWMIN
*
         LDA   ]OLDMAX    ; {3C2B} SUBTRACT OLDMIN
         SEC              ; {2C1B} FROM OLDMAX, STORE
         SBC   ]OLDMIN    ; {3C2B} IN OLDRANGE
         STA   ]OLDRNG    ; {4C3B}
         LDA   ]NEWMAX    ; {4C3B} SUBTRACT NEWMIN
         SEC              ; {2C1B} FROM NEWMAX, THEN
         SBC   ]NEWMIN    ; {4C3B} STORE IN NEWRANGE
         STA   ]NEWRNG    ; {4C3B}
         LDA   ]OLDVAL    ; {4C3B} SUBTRACT OLDMIN
         SEC              ; {2C1B} FROM OLDVAL AND
         SBC   ]OLDMIN    ; {3C2B} STORE IN VALRANGE
         STA   ]VALRNG    ; {4C3B}
*
** GET MULRANGE: VALRANGE * NEWRANGE
*
         LDA   #00        ; {3C2B} CLEAR ACCUMULATOR,
         TAY              ; {2C1B} .Y AND THE HIGH BYTE
         STY   ]NUM1HI    ; {4C3B}
         BEQ   :ENTLP     ; {3C2B} IF ZERO, BRANCH
:DOADD
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]VALRNG    ; {4C3B} ADD VALUE RANGE TO .A
         TAX              ; {2C1B} HOLD IN .X
         TYA              ; {2C1B} .Y BACK TO .A
         ADC   ]NUM1HI    ; {4C3B} ADD HIBYTE
         TAY              ; {2C1B} MOVE BACK TO .Y
         TXA              ; {2C1B} .X BACK TO .A
:MLP
         ASL   ]VALRNG    ; {5C2B} SHIFT VALUE RANGE
         ROL   ]NUM1HI    ; {5C2B} ADJUST HIGH BYTE
:ENTLP
         LSR   ]NEWRNG    ; {5C2B} SHIFT NEW RANGE
         BCS   :DOADD     ; {3C2B} IF LAST BIT WAS 1, LOOP ADD
         BNE   :MLP       ; {3C2B} IF ZERO FLAG CLEAR, LOOP SHIFT
         STA   ]MULRNG    ; {4C3B} STORE RESULT LOW BYTE
         STY   ]MULRNG+1  ; {4C3B} STORE HIGH BYTE
*
** NOW GET DIVRANGE: MULRANGE / OLDRANGE
*
:DIVIDE
         LDA   #0         ; {3C2B} CLEAR ACCUMULATOR
         STA   ]REMAIN    ; {4C3B} AND THE REMAINDER LOBYTE
         STA   ]REMAIN+1  ; {4C3B} AND REMAINDER HIBYTE
         LDX   #16        ; {3C2B} NUMBER OF BYTES
:DIVLP
         ASL   ]MULRNG    ; {5C2B} LOW BYTE * 2
         ROL   ]MULRNG+1  ; {5C2B} HIGH BYTE * 2
         ROL   ]REMAIN    ; {5C2B} REMAINDER LOW BYTE * 2
         ROL   ]REMAIN+1  ; {5C2B} HIGH BYTE * 2
         LDA   ]REMAIN    ; {4C3B} SUBTRACT OLDRANGE
         SEC              ; {2C1B} FROM REMAINDER
         SBC   ]OLDRNG    ; {4C3B}
         TAY              ; {2C1B} HOLD IN .Y
         LDA   ]REMAIN+1  ; {4C3B} SUBTRACT HIGH BYTES
         SBC   ]OLDRNG+1  ; {4C3B}
         BCC   :SKIP      ; {3C2B} IF NO CARRY, THEN NOT DONE
         STA   ]REMAIN+1  ; {4C3B} SAVE SBC AS NEW REMAINDER
         STY   ]REMAIN    ; {4C3B}
         INC   ]DIVRNG    ; {6C3B} INCREMENT THE RESULT
:SKIP    DEX              ; {2C1B} DECREMENT COUNTER
         BNE   :DIVLP     ; {3C2B} IF ZERNO, RELOOP
*
** NOW ADD NEWMIN TO DIVRANGE
*
         LDA   ]DIVRNG    ; {4C3B} USE LOW BYTE ONLY
         CLC              ; {2C1B} AND ADD TO ]NEWMIN
         ADC   ]NEWMIN    ; {4C3B} TO GET THE NEW VALUE
         STA   ]NEWVAL    ; {4C3B}
         STA   RETURN     ; {4C3B} COPY TO RETURN
         LDX   #1         ; {3C2B} RETURN LENGTH
         STX   RETLEN     ; {4C3B}
         RTS              ; {6C1B}


THE RND16 MACRO

SUMMARY

Condition Value
Name RND16
Type Macro
File MAC.MATHRND.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate an 16-bit pseudorandom number
Input none
Output none
Dependencies RND16
Flags Destroyed NZCV
Cycles 101+
Bytes 63
Notes None
See Also RND8 RAND16

DETAILS

The RND16 macro generates a 16-bit pseudorandom number. After being called, the value is stored in RETURN as well as in the .A (low byte) and .X (high byte) registers. RETLEN holds #2, the byte-length of the number.

LISTING 4.97: RND16 Macro Source

*
*``````````````````````````````*
* RND16         (NATHAN RIGGS) *
*                              *
* RETURN A 16-BIT PSEUDORANDOM *
* NUMBER.                      *
*                              *
* PARAMETERS                   *
*                              *
*  NONE                        *
*                              *
* CYCLES: 101+                 *
* SIZE: 63 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
RND16    MAC
         JSR   RAND16     ; {101C63B}
         <<<
*


THE RAND16 SUBROUTINE

SUMMARY

Condition Value
Name RAND16
Type Subroutine
File SUB.RAND16.ASM
Author Nathan Riggs
Last Revision 02-APR-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Generate a 16-bit pseudorandom number
Input none
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 95+
Bytes 60
Notes None
See Also RND16

DETAILS

The RAND16 subroutine generates a pseudorandom number between 0 and 65,535 (16-bits). This value is stored in RETURN with its byte-length, two, in RETLEN. Additionally, the value is returned in the .A (low byte) and .X (high byte) registers.

LISTING 4.98: RANDB Subroutine Source

*``````````````````````````````*
* RAND16 : 16BIT RANDOM NUMBER *
*                              *
* GENERATE A 16BIT PSEUDO-     *
* RANDOM NUMBER AND RETURN IT  *
* IN A,X (LOW, HIGH).          *
*                              *
*------------------------------*
* ORIGINAL AUTHOR IS WHITE     *
* FLAME, AS SHARED ON          *
* CODEBASE64.                  *
*------------------------------*
*                              *
* INPUT:                       *
*                              *
*  NONE                        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 95+                  *
* SIZE: 60 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]SEED    EQU   WPAR1      ; SEED FOR PRNG
*
RAND16
         LDA   RNDL       ; {3C2B} GET SEED LOBYTE
         STA   ]SEED      ; {3C2B}
         LDA   RNDH       ; {3C2B} GET SEED HIBYTE
         STA   ]SEED+1    ; {3C2B}
*
         LDA   ]SEED      ; {3C2B} CHECK IF $0 OR $8000
         BEQ   :LOW0      ; {3C2B}
*
** DO A NORMAL SHIFT
*
         ASL   ]SEED      ; {5C2B} MUTATE
         LDA   ]SEED+1    ; {3C2B}
         ROL              ; {2C1B}
         BCC   :NOEOR     ; {3C2B} IF CARRY CLEAR, EXIT
:DOEOR                    ; HIGH BYTE IN A
         EOR   ]MAGEOR+1  ; {3C2B} EOR WITH MAGIC NUMBER
         STA   ]SEED+1    ; {3C2B} STORE BACK INTO HIBYTE
         LDA   ]SEED      ; {3C2B}
         EOR   ]MAGEOR    ; {3C2B} DO SAME WITH LOW BYTE
         STA   ]SEED      ; {3C2B}
         JMP   :EXIT      ; {3C3B}
:LOW0
         LDA   ]SEED+1    ; {3C2B}
         BEQ   :DOEOR     ; {3C2B} IF HI ALSO 0, APPLY EOR
         ASL              ; {2C1B}
         BEQ   :NOEOR     ; {3C2B} IF 00, THEN IT WAS $80
         BCS   :DOEOR     ; {3C2B} ELSE DO EOR
:NOEOR
         STA   ]SEED+1    ; {3C2B}
:EXIT
         LDX   ]SEED+1    ; {3C2B} VAL HIBYTE IN .X
         LDY   ]SEED      ; {3C2B} LOBYTE TEMP IN .Y
         STX   RNDH
         STY   RNDL
         STY   RETURN     ; {4C3B} TRANSFER TO RETURN AREA
         STX   RETURN+1   ; {4C3B}
         LDA   #2         ; {3C2B} LENGTH OF RETURN IN BYTES
         STA   RETLEN     ; {4C3B}
         TYA              ; {2C1B} TRANSFER LOBYTE TO .A
         RTS              ; {6C1B}


PART II: MATH COLLECTION DEMONSTRATIONS

The following demo programs illustrate how to use the macros in the math collection that deal with dividing by constants, general-purpose integer math routines for 8-bit and 16-bit addition, subtraction, multiplication and division, and macros dedicated to generating and manipulating pseudorandom numbers. These span three different demo programs, grouped together as presented here. Note that these are not extensive tests, and should not be mistaken as such; they merely show the basic usage of the macros and one instance of each macro working correctly. The purpose of the demo files is to provide assistance to beginners rather than to do a thorough test of every subroutine.

LISTING 4.9A: The DEMO.MATHBY.ASM File Source

*
*``````````````````````````````*
* DEMO.MATH                    *
*                              *
* A DEMO OF THE INTEGER MATH   *
* MACROS INCLUDED AS PART OF   *
* THE APPLEIIASM LIBRARY.      *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      16-JUL-2019       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** ASSEMBLER DIRECTIVES
*
         CYC   AVE
         EXP   OFF
         TR    ON
         DSK   DEMO.MATHBY
         OBJ   $BFE0
         ORG   $6000
*
*``````````````````````````````*
*  TOP INCLUDES (HOOKS,MACROS) *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         PUT   MIN.HEAD.REQUIRED.ASM
         USE   MIN.MAC.REQUIRED.ASM
         PUT   MIN.HEAD.MATH.ASM
         USE   MIN.MAC.M8BY.ASM
         USE   MIN.MAC.M16BY.ASM
         USE   MIN.MAC.D8BY.ASM
]HOME2   EQU   $FC58
*
*``````````````````````````````*
*      PROGRAM MAIN BODY       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         JSR   ]HOME2
*
** THIS DEMO SHOWS HOW TO USE THE QUICK
** MATH MACROS AVAILABLE FOR USE AS ALTERNATIVES
** TO THE NORMAL MATH ROUTINES. THESE MACROS
** DO NOT CALL ANY ROUTINES, AND ALL PASSING
** OF VARIABLES IS DONE VIA THE REGISTERS. THESE
** TEND TO BE QUICKER BECAUSE WE ARE MULTIPLYING
** AND DIVIDING BY CONSTANTS, THUS NOT REQUIRING
** THE USE OF LOOPING, CHECKING VALUES, ETC.
** EVERYTHING IS STRAIGHTFORWARDLY DEDICATED TO
** ONLY A SINGLE FUNCTION.
*
** WE SHALL START WITH 8-BIT MULTIPLICATION MACROS,
** FOLLOWED BY 16-BIT MULTIPLICATION, THEN 8-BIT
** DIVISION. CURRENTLY, NO 16-BIT DIVISION QUICK
** MATH ROUTINES EXIST, BECAUSE THE CYCLES SAVED IN
** COMPARISON TO THE BYTES USED WOULD PROBABLY BE
** MINIMAL.
*
*``````````````````````````````*
* 8-BIT QUICK MULTIPLICATION   *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** STARTING WITH THE LOWEST NUMBER TO MULTIPLY BY,
** THE NUMBER TWO.
*
         JSR   ]HOME2
         _PRN  "8-BIT CONSTANT MATH MACROS",8D
         _PRN  "==========================",8D8D
         _PRN  "#5 * 2 = ",8D8D
         M8BY2 BIT8
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY3 BIT8
         STA   RETURN
         _PRN  "#5 * #3 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY4 BIT8
         STA   RETURN
         _PRN  "#5 * #4 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY5 BIT8
         STA   RETURN
         _PRN  "#5 * #5 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY6 BIT8
         STA   RETURN
         _PRN  "#5 * #6 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY7 BIT8
         STA   RETURN
         _PRN  "#5 * #7 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY8 BIT8
         STA   RETURN
         _PRN  "#5 * #8 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY9 BIT8
         STA   RETURN
         _PRN  "#5 * #9 = ",8D8D
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         M8BY10 BIT8
         STA   RETURN
         _PRN  "#5 * #10 = ",8D8D
         DUMP  #RETURN;#1
         _WAIT
*
*``````````````````````````````*
* 16-BIT CONST MULTIPLICATION  *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** NOW WE WILL TEST THE 16-BIT MULTIPLY-BY-
** A-CONSTANT MACROS.
*
         JSR   ]HOME2
         _PRN  "16-BIT CONSTANT MULTIPLICATION",8D
         _PRN  "==============================",8D8D
*
         _PRN  "#500 * #2 = ",8D8D
         MBY2  BIT16
         STA   RETURN
         STX   RETURN+1
         DUMP  #RETURN;#2
         _WAIT
*
         _PRN  " ",8D8D
         MBY3  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #3 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY4  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #4 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY5  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #5 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY6  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #6 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY7  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #7 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY8  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #8 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY9  BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #9 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY10 BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #10 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
         _PRN  " ",8D8D
         MBY1H BIT16
         STA   RETURN
         STX   RETURN+1
         _PRN  "#500 * #100 = ",8D8D
         DUMP  #RETURN;#2
         _WAIT
         _PRN  " ",8D8D
*
*``````````````````````````````*
* 8BIT DIVISION BY CONSTANTS   *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         JSR   ]HOME2
         _PRN  "8-BIT DIVISION BY CONSTANTS",8D
         _PRN  "===========================",8D8D
*
         _PRN  "#100 / 2 = ",8D8D
         D8BY2 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 3 = ",8D8D
         D8BY3 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 4 = ",8D8D
         D8BY4 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 5 = ",8D8D
         D8BY5 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 6 = ",8D8D
         D8BY6 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 7 = ",8D8D
         D8BY7 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 8 = ",8D8D
         D8BY8 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
         _PRN  "#100 / 9 = ",8D8D
         D8BY9 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
*
*
         _PRN  "#100 / 10 = ",8D8D
         D8BY10 BIT82
         STA   RETURN
         DUMP  #RETURN;#1
         _PRN  " ",8D8D
         _WAIT
         JMP   REENTRY
*
*``````````````````````````````*
*        BOTTOM INCLUDES       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BOTTOM INCLUDES
*
         PUT   MIN.LIB.REQUIRED.ASM
*
BIT8     HEX   05         ; #5
BIT82    HEX   64
BIT16    HEX   F401       ; #500

LISTING 4.9B: The DEMO.MATHBAS.ASM File Source

*
*``````````````````````````````*
* DEMO.MATHBAS.ASM             *
*                              *
* A DEMO OF THE 8-BIT AND THE  *
* 16-BIT MACROS FOR ADDING,    *
* SUBTRACTING, MULTIPLYING AND *
* DIVIDING. A 16-BIT COMPARE   *
* MACRO IS ALSO INCLUDED AS    *
* PART OF THE COLLECTION.      *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      02-APR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** ASSEMBLER DIRECTIVES
*
         CYC   AVE
         EXP   OFF
         TR    ON
         DSK   DEMO.MATHBAS
         OBJ   $BFE0
         ORG   $6000
*
*``````````````````````````````*
*  TOP INCLUDES (HOOKS,MACROS) *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         PUT   MIN.HEAD.REQUIRED.ASM
         USE   MIN.MAC.REQUIRED.ASM
         PUT   MIN.HEAD.MATH.ASM
         USE   MIN.MAC.MATH8.ASM
         USE   MIN.MAC.MATH16.ASM
]HOME2   EQU   $FC58
*
*``````````````````````````````*
*      PROGRAM MAIN BODY       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         JSR   ]HOME2
*
*``````````````````````````````*
* 8-BIT BASIC MATH MACROS      *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THIS COLLECTION CONTAINS MACROS FOR 8-BIT
** BASIC MATH, INCLUDING ADDITION, SUBTRACTION,
** MULTIPLICATION AND DIVISION. CURRENTLY, ONLY
** UNSIGNED NUMBERS ARE SUPPORTED, THOUGH THIS
** WILL LIKELY CHANGE IN A NEAR-FUTURE REVISION.
*
*``````````````````````````````*
* 8-BIT ADDITION               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** 8-BIT ADDITION IS RATHER TRIVIAL, BUT IS
** INCLUDED HERE FOR BEGINNERS' REFERENCE. IF
** YOU ARE CAPABLE OF WRITING THESE ROUTINES
** YOURSELF, YOU ARE LIKELY TO SAVE AT LEAST
** 8 CYCLES, AS THE MACRO USES THE RETURN
** ADDRESS FOR PASSING BACK THE SUM. THIS SUM
** IS ALSO PASSED BACK VIA THE .A REGISTER,
** BUT THERE ARE STILL WASTED CYCLES.
*
** ADDITION IS PARTICULARLY SIMPLE: PASS THE
** TWO BYTE VALUES TO BE ADDED, THEN EXPECT
** THE SUM IN .A AS WELL AS IN RETURN.
*
** NOTE THAT CURRENTLY, THE 8-BIT ADDITION
** AND SUBTRACTION ROUTINES ONLY ACCEPT A
** DIRECT ADDRESS, AND THUS DOES NOT ALLOW
** FOR THE INDIRECT ADDRESSING WORKAROUND THAT
** MOST OF THE REST OF THE LIBRARY USES. THIS
** IS FOR THE SAKE OF PRESERVING CYCLES AND
** DISCARDING BYTES.
*
         JSR   ]HOME2
         _PRN  "8-BIT ADDITION",8D
         _PRN  "==============",8D8D
         _PRN  "10 + 20 =",8D
         ADD8  NUM81;NUM82
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 8-BIT SUBTRACTION            *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** 8-BIT SUBTRACTION WORKS THE SAME WAY AS
** ADDITION (EXCEPT, OBVIOUSLY, IN THE FACT
** THAT THEY ARE OPPOSITE OPERATIONS), AND
** ALSO HAS THE SAME LIMITATION: NO ADDRESSING
** MODES OTHER THAN THE STANDARD PASSING OF
** ADDRESSES WHERE THE ARGUMENT VALUES ARE
** LOCATED.
*
         JSR   ]HOME2
         _PRN  "8-BIT SUBTRACTION",8D
         _PRN  "=================",8D8D
         _PRN  "20 - 10 =",8D
         SUB8  NUM82;NUM81
         DUMP  #RETURN;#1
         _WAIT
*
*``````````````````````````````*
* 8-BIT MULTIPLICATION         *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** 8-BIT MULTIPLICATION IS A BIT MORE COMPLICATED
** THAN ADDITION AND SUBTRACTION UNDER THE HOOD,
** BUT CALLING IT REMAINS THE SAME. LIKE WITH
** THE OTHER 8-BIT BASIC MATH MACROS, ONLY LITERALS
** AND DIRECT ADDRESSES ARE ACCEPTED AS PARAMETERS,
** UNLIKE THE REST OF THE LIBRARY, TO SAVE RESOURCES
** IN SUBROUTINES THAT ARE LIKELY TO BE CALLED MUCH
** MORE THAN OTHERS AS PART OF A PROGRAM (AND OFTEN
** IN LOOPS).
*
         JSR   ]HOME2
         _PRN  "8-BIT MULTIPLICATION",8D
         _PRN  "====================",8D8D
         _PRN  "10 * 20 = ",8D
         MUL8  NUM81;NUM82
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 8-BIT DIVISION               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THIS MACRO IS USED LIKE ALL OTHER 8-BIT
** MACROS, BUT THE ORDER IS IMPORTANT HERE:
** THE FIRST VALUE PASSED IS THE DIVIDEND
** WHILE THE SECOND VALUE US THE DIVISOR. IT
** MAY HELP TO THINK OF THE SEMI-COLON HERE
** AS STANDING FOR "BY" SO THAT THE STATEMENT
** CAN BE READ AS "DIVIDE DIVIDEND BY DIVISOR."
*
** 8-BIT DIVISION IS LIMITED TO ARGUMENTS THAT
** ARE EITHER A DIRECT ADDRESS OR A LITERAL VALUE,
** LIKE OTHER 8-BIT MATH ROUTINES.
*
         JSR   ]HOME2
         _PRN  "8-BIT DIVISION",8D
         _PRN  "==============",8D8D
         _PRN  "20 / 10 = ",8D
         DIV8  NUM82;NUM81
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 16-BIT BASIC MATH MACROS     *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BOTH ADDITION AND SUBTRACTION OF 16-BIT
** NUMBERS IS ALSO RATHER TRIVIAL, BUT CAN
** BE CONFUSING TO SOMEONE NEW TO 6502
** ASSEMBLY (ESPECIALLY WITHOUT A FULL
** UNDERSTANDING OF HOW ADC WORKS). EVEN STILL,
** IT CAN BECOME A BIT TEDIOUS TO CONSTANTLY
** WRITE OUT THE ROUTINES MANUALLY, AS THEY DO
** CONSTITUTE A SMALL NUMBER OF BYTES THAT CAN
** GET TIRESOME ON REPEAT.
*
*``````````````````````````````*
* 16-BIT ADDITION              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** USING THE 16-BIT ADDITION MACRO IS SIMILAR TO ITS
** 8-BIT COUSIN: TWO ADDRESSES ARE PROVIDED THAT HOLD
** THE VALUES TO BE ADDED. THE TWO-BYTE SUM IS THEN
** PASSED BACK VIA RETURN (WITH RETLEN HOLDING ITS
** LENGTH, 2) AS WELL AS IN .A (LOW BYTE) AND .X (HIGH).
*
** LIKE 8-BIT ADDITION, 16-BIT ADDITION ALSO HAS EXTRA
** BYTES AND CYCLES THAT CAN BE EASILY DISCARDED EITHER
** BY ALTERING THE MACRO AND RELATED SUBROUTINE ITSELF OR
** BY SIMPLY DOING THE ADDITION MANUALLY.
*
         JSR   ]HOME2
         _PRN  "16-BIT ADDITION",8D
         _PRN  "===============",8D8D
         ADD16 NUM161;NUM162
         _PRN  "300 + 400 =",8D
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 16-BIT SUBTRACTION           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** 16-BIT SUBTRACTION FOLLOWS THE SAME SETUP
** AND RULES AS 16-BIT ADDITION:
*
         JSR   ]HOME2
         _PRN  "16-BIT SUBTRACTION",8D
         _PRN  "==================",8D8D
         _PRN  "400 - 300 = ",8D
         SUB16 NUM162;NUM161
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 16-BIT MULTIPLICATION        *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BY NOW, THE METHOD SHOULD BE OBVIOUS: MUL16
** TAKES TWO ARGUMENTS WHICH ARE ADDRESSES THAT
** HOLD THE TWO VALUES TO BE MULTIPLIED.
*
         JSR   ]HOME2
         _PRN  "16-BIT MULTIPLICATION",8D
         _PRN  "=====================",8D8D
         _PRN  "300 * 400 = ",8D
         MUL16 NUM161;NUM162
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 16-BIT DIVISION              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** 16-BIT DIVISION WORKS LIKE 8-BIT DIVISION,
** WITH THE RESULT STORED IN RETURN (2 BYTES)
** AS WELL AS IN .A (LOW BYTE) AND .X (HIGH).
** ADDITIONALLY, THE REMAINDER IS HELD IN THE
** .Y REGISTER--A MODULUS FUNCTION CAN SIMPLY
** CALL THIS DIVISION MACRO AND THEN READ THE
** VALUE OF .Y FOR THE ANSWER.
*
         JSR   ]HOME2
         _PRN  "16-BIT DIVISION",8D
         _PRN  "===============",8D8D
         _PRN  "400 / 300 = ",8D
         DIV16 NUM162;NUM161
         DUMP  #RETURN;RETLEN
         _WAIT
*
*``````````````````````````````*
* 16-BIT COMPARISON            *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** LASTLY, A 16-BIT COMPARISON MACRO IS PROVIDED
** THAT MIMICS THE FUNCTIONALITY OF THE CMP INSTRUCTION,
** BUT OF COURSE FOR 16-BIT VALUES. THE ADDRESSES
** OF TWO SEPARATE VALUES ARE PROVIDED, AND THEN THE
** COMPARISON IS MADE WITH THE FOLLOWING RESULTS:
*
** Z FLAG = 1 IF BOTH VALUES ARE EQUAL
** C FLAG = 0 IF FIRST IS GREATER THAN SECOND
** C FLAG = 1 IF FIRST IS LESS THAN OR EQUAL TO SECOND
** N FLAG = 1 IF A SIGNED FIRST IS GREATER THAN A SIGNED SECOND
** N FLAG = 0 IF SIGNED FIRST IS LESS THAN OR EQUAL TO
**            THE SIGNED SECOND PARAMETER
*
         JSR   ]HOME2
         _PRN  "16-BIT COMPARISON",8D
         _PRN  "=================",8D8D
         _PRN  "CMP16 #300;#400",8D8D
         CMP16 NUM161;NUM162
         BEQ   :GREATER
         BNE   :LESSOREQ
:GREATER
         _PRN  "FIRST IS GREATER THAN SECOND.",8D8D
         JMP   :EXIT
:LESSOREQ
         _PRN  "FIRST IS <= THE SECOND PARAMETER.",8D8D
:EXIT
         _WAIT
*
         JSR   ]HOME2
         _PRN  "DONE.",8D8D8D
*
         JMP   REENTRY
*
*``````````````````````````````*
*        BOTTOM INCLUDES       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BOTTOM INCLUDES
*
         PUT   MIN.LIB.REQUIRED.ASM
*
** INDIVIDUAL SUBROUTINE INCLUDES
*
** 8-BIT MATH SUBROUTINES
*
         PUT   MIN.SUB.MULTU8.ASM
         PUT   MIN.SUB.DIVDU8.ASM
*
** 16-BIT MATH SUBROUTINES
*
         PUT   MIN.SUB.ADDIT16.ASM
         PUT   MIN.SUB.SUBT16.ASM
         PUT   MIN.SUB.COMP16.ASM
         PUT   MIN.SUB.MULTU16.ASM
         PUT   MIN.SUB.DIVDU16.ASM
*
NUM81    DB    10
NUM82    DB    20
NUM161   DW    300
NUM162   DW    400

LISTING 3.9C: The DEMO.MATHRND.ASM File Source

*
*``````````````````````````````*
* DEMO.MATH                    *
*                              *
* A DEMO OF THE INTEGER MATH   *
* MACROS INCLUDED AS PART OF   *
* THE APPLEIIASM LIBRARY.      *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      02-APR-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** ASSEMBLER DIRECTIVES
*
         CYC   AVE
         EXP   OFF
         TR    ON
         DSK   DEMO.MATHRND
         OBJ   $BFE0
         ORG   $6000
*
*``````````````````````````````*
*  TOP INCLUDES (HOOKS,MACROS) *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         PUT   MIN.HEAD.REQUIRED.ASM
         USE   MIN.MAC.REQUIRED.ASM
         PUT   MIN.HEAD.MATH.ASM
         USE   MIN.MAC.MATHRND.ASM
]HOME2   EQU   $FC58
*
*``````````````````````````````*
*      PROGRAM MAIN BODY       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
*``````````````````````````````*
* PSEUDORANDOM NUMBER MACROS   *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THERE ARE FIVE MACROS DEDICATED TO USING AND
** GENERATING PSEUDORANDOM NUMBERS. THE RND8
** MACRO AND THE RND16 MACRO GENERATE EITHER 8-BIT
** OR 16-BIT RANDOM NUMBERS, RESPECTIVELY, WHILE
** THE RAND MACRO GENERATES AN 8-BIT NUMBER BETWEEN
** A LOW AND A HIGH.
*
** IN ADDITION TO THESE ARE TWO OTHER IMPORTANT MACROS:
** THE RNDMZ MACRO AND THE RNDEOR MACRO. THESE ARE BOTH
** DEDICATED TO ALTERING THE SEED AND THE EOR VALUE
** FOR GENERATING PSEUDORANDOM NUMBERS, BUT THE RNDEOR
** ALLOWS YOU TO DIRECTLY SPECIFY THE SEED AND THE EOR
** VALUE WHEREAS THE RNDMZ MACRO ALLOWS YOU TO SET THE
** SEED DIRECTLY BUT NOT THE EOR VALUE. INSTEAD, THE
** VALUE PASSED FOR THE EOR ARGUMENT IS DIVIDED BY FOUR
** TO SET IT TO A NUMBER BETWEEN 0 AND 63, AND A FINAL
** EOR VALUE IS CHOSEN FROM A TABLE OF CONSTANTS THAT
** ENSURES MAXIMUM VARIABILITY (TO THE POINT OF BEING
** "UNNATURAL" RANDOMNESS).
*
** EITHER RNDMZ OR RNDEOR SHOULD BE EXECUTED BEFORE
** RND8, RND16, OR RAND ARE USED. OTHERWISE, THE SEED
** AND EOR VALUE WILL REVERT TO DEFAULT VALUES,
** POSSIBLY BECOMING HIGHLY PREDICTABLE BY SOMEONE
** LOOKING TO EXPLOIT SUCH SYSTEMS.
*
*``````````````````````````````*
* THE RNDEOR MACRO             *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** AS NOTED ABOVE, THE RNDEOR MACRO ALLOWS YOU TO SET
** THE SEED AND EOR VALUE FOR THE PSEUDORANDOM NUMBER
** GENERATOR. THE SEED IS PROVIDED FIRST, FOLLOWED BY
** THE EOR "MAGIC NUMBER."
*
         JSR   ]HOME2
         _PRN  "THE RNDEOR MACRO",8D
         _PRN  "================",8D8D
         RNDEOR SEED1;NUM1
         _PRN  "SEED LOW AND HIGH NOW:",8D
         DUMP  #RNDL;#2
         _PRN  " ",8D8D
         _PRN  "AND THE MAGIC NUMBER IS:",8D
         DUMP  #]MAGEOR;#2
         _WAIT
*
*``````````````````````````````*
* THE RNDMZ MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** AS DESCRIBED ABOVE, THE RNDMZ (RANDOMIZE) MACRO
** SETS THE SEED OF THE PRNG TO A GIVEN VALUE, AND
** PULLS FROM A TABLE OF PRESET VALUES THE "MAGIC
** NUMBER" THAT IS USED TO EOR THE SEED. THE NUMBER
** PROVIDED AS ARGUMENT TWO SERVES AS AN INDEX.
*
         JSR   ]HOME2
         _PRN  "THE RNDMZ MACRO",8D
         _PRN  "===============",8D8D
         RNDMZ SEED2;NUM2
         _PRN  "THE NEW SEED IS: ",8D
         DUMP  #RNDL;#2
         _PRN  " ",8D8D
         _PRN  "AND THE NEW MAGIC NUMBER IS:",8D
         DUMP  #]MAGEOR;#2
         _WAIT
*
*``````````````````````````````*
* THE RND8 MACRO               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE RND8 MACRO RETURNS A PSEUDORANDOM NUMBER
** BETWEEN 0 AND 255 (THUS THE 8, FOR 8-BIT).
** THIS IS PASSED BACK VIA RETURN AND .A.
*
         JSR   ]HOME2
         _PRN  "THE RND8 MACRO",8D
         _PRN  "==============",8D8D
         _PRN  "SOME RANDOM NUMBERS:",8D8D
         RND8
         DUMP  #RETURN;#1
         _PRN  " "
         RND8
         DUMP  #RETURN;#1
         _PRN  " "
         RND8
         DUMP  #RETURN;#1
         _WAIT
*
*``````````````````````````````*
* THE RAND MACRO               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE RAND MACRO TAKES A LOW VALUE AND A
** HIGH VALUE AND PASSES BACK A RANDOM NUMBER
** BETWEEN THE TWO IN RETURN AND .A.
*
         JSR   ]HOME2
         _PRN  "THE RAND MACRO",8D
         _PRN  "==============",8D8D
         _PRN  "SOME RANDOM NUMBERS:",8D8D
         RAND  #1;#30
         DUMP  #RETURN;#1
         _PRN  " "
         RAND  #1;#30
         DUMP  #RETURN;#1
         _PRN  " "
         RAND  #1;#30
         DUMP  #RETURN;#1
         _WAIT
*
*``````````````````````````````*
* THE RND16 MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE RND16 MACRO WORKS THE SAME WAY AS
** THE RND8 MACRO, EXCEPT THAT IT PASSES BACK
** A 16-BIT RANDOM VALUE VIA RETURN AS WELL AS
** IN .A (LOW BYTE) AND .X (HIGH).
*
         JSR   ]HOME2
         _PRN  "THE RND16 MACRO",8D
         _PRN  "==============",8D8D
         _PRN  "SOME RANDOM NUMBERS:",8D8D
         RND16
         DUMP  #RETURN;#2
         _PRN  " "
         RND16
         DUMP  #RETURN;#2
         _PRN  " "
         RND16
         DUMP  #RETURN;#2
         _WAIT
*
         JSR   ]HOME2
         _PRN  "FIN!",8D8D8D
*
         JMP   REENTRY
*
*``````````````````````````````*
*        BOTTOM INCLUDES       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BOTTOM INCLUDES
*
         PUT   MIN.LIB.REQUIRE
*
** INDIVIDUAL SUBROUTINE INCLUDES
*
         PUT   MIN.SUB.RAND8.ASM
         PUT   MIN.SUB.RANDB.ASM
         PUT   MIN.SUB.RAND16.ASM
*
SEED1    DW    1000
NUM1     DW    666
SEED2    DW    2000
NUM2     DB    200