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