#### The C64 OS Programmer's Guide is being written

This guide is being written and released and few chapters at a time. If a chapter seems to be empty, or if you click a chapter in the table of contents but it loads up Chapter 1, that's mostly likely because the chapter you've clicked doesn't exist yet.

Discussion of development topics are on-going about what to put in this guide. The discusssions are happening in the C64 OS Community Support Discord server, available to licensed C64 OS users.

# C64 OS PROGRAMMER'S GUIDE

## Chapter 4: Using the KERNAL → Math (module)

#### 16-bit Integer Arithmetic

These two routines are used to perform 16-bit multiplication and division. They can easily be used for 8-bit multiplication and division as well, since the multiplication of two 8-bit numbers so easily overflows an 8-bit result. 16-bit addition and subtraction are best handled using the standard macros defined in //os/s/:math.s, and floating point math operations are best handled using the BASIC ROM and its routines which are defined in //os/s/:float.s and //os/h/:float.h.

The workspace memory addresses used as the input and output parameters for these routines are in zero page, are the same workspace area used by the BASIC ROM for math operations, and are defined in //os/s/:math.s.

#### mul16

Purpose | Multiply two 16-bit integers. |
---|---|

Module offset | 0 |

Communication registers | None |

Stack requirements | 2 bytes |

Zero page usage | $61, $62, $63, $64, $65, $66, $67, $68 |

Registers affected | A, Y |

Input parameters |
multplr → 16-bit multiplier multcnd → 16-bit multiplicand |

Output parameters | product ← 16-bit product |

**Description: ** This routine is used to multiply two 16-bit integers and may
result in up to a 32-bit product. Multplr is modified by this routine. Multcnd is not affected
by this routine. The input and output parameters are in zero page, and are defined by
//os/s/:math.s.

#### div16

Purpose | Divide two 16-bit integers. |
---|---|

Module offset | 3 |

Communication registers | Status |

Stack requirements | 2 bytes |

Zero page usage | $61, $62, $63, $64, $65, $66, $67 |

Registers affected | A, X, Y |

Input parameters |
C → SET to round the result C → CLR to not round result divisor → 16-bit divisor dividnd → 16-bit dividend |

Output parameters |
divrslt ← 16-bit quotient remandr ← remainder |

**Description: ** This routine is used to divide two 16-bit integers which
results in a 16-bit quotient returned in divrslt. The 16-bit remainder is returned in
remandr. If the carry is set when this routine is called, then a remainder that is greater
than half the divisor is used to round the result up by one. Opting to use rounding causes
the remainder to be multiplied by 2. Dividnd is modified by this routine. Divisor is not
affected by this routine. The input and output parameters are in zero page, and are defined
by //os/s/:math.s.

#### Integer ⇆ String Conversion

These three routines are used to convert an integer to a string or a string to an integer, in different bases up to a maximum of base 10. And lastly one routine to convert an 8-bit unsigned integer to hexadecimal, a string in base 16.

#### tostr

Purpose | Convert a 16-bit integer to string. |
---|---|

Module offset | 6 |

Communication registers | None |

Stack requirements | 4 bytes |

Zero page usage | $61, $62, $63, $64, $65, $66, $67 |

Registers affected | A, X, Y |

Input parameters |
divisor → base (maximum 10) dividnd → 16-bit integer value |

Output parameters |
RegPtr ← pointer to string |

**Description: ** This routine is used to convert a 16-bit integer to a
string representation. The string representation can be in any base from 2 to 10.
Write the base in to divisor. The maximum base supported by this routine is 10. Divisor
is a 16-bit number, so remember to write the $00 into the divisor high byte. Write the
16-bit integer to be converted into dividnd. Call the routine, and a pointer to the
string representation is returned as a RegPtr. The input parameters are in zero page,
and are defined by //os/s/:math.s. This routine calls div16 internally. Divisor is not
affected by this routine.

#### toint

Purpose | Convert a string representation of a number to a 16-bit integer. |
---|---|

Module offset | 9 |

Communication registers | A, X, Y |

Stack requirements | 5 bytes |

Zero page usage | $61, $62, $63, $64, $65, $66, $67, $68 |

Registers affected | A, X, Y |

Input parameters |
multcnd → base (maximum 10) RegPtr → pointer to string A → string length (optional) |

Output parameters |
multplr ← 16-bit integer value |

**Description: ** This routine is used to convert a string representation
of a number to a 16-bit integer. The string representation can be in any base from 2 to 10.
Write the base in to multcnd. The maximum base supported by this routine is 10. Multcnd
is a 16-bit number, so remember to write the $00 into the multcnd high byte. Read a pointer
to a string into a RegPtr. If the number in the string ends with the end of the string,
load #$ff into the accumulator. Alternatively, load into the accumulator the string length
to be converted. Call the routine, and the 16-bit integer value is returned in multplr.
The input parameters are in zero page, and are defined by //os/s/:math.s. This routine
calls mul16 internally. Multcnd is not affected by this routine.

#### tohex

Purpose | Convert a byte to string representation in hexadecimal. |
---|---|

Module offset | 12 |

Communication registers | A, X, Y |

Stack requirements | 4 bytes |

Zero page usage | None |

Registers affected | A, X, Y |

Input parameters | A → 8-bit unsigned integer (0 to 255) |

Output parameters |
X ← Lower nybble as PETSCII character Y ← Upper nybble as PETSCII character |

**Description: ** This routine is used to convert a single byte into its
string equivalent in hexadecimal. The technique used is much more efficient than that
used by tostr. To convert a 16-bit number, this routine has to be called twice.
Load the byte value into the accumulator, call this routine, and the X and Y registers
are returned with PETSCII values from "0" to "9" and "A" to "F".

#### KERNAL Modules in Alphabetical Order

#### KERNAL Modules in Module Lookup Table Order

### Return to Using the KERNAL → KERNAL Modules

### Table of Contents

## This document is subject to revision updates.

Last modified: Apr 20, 2023