Creating a Fraction Converter for the Commodore 64 in Assembly Language (6510/6502)
Tags: commodore64, retrocomputing, assemblylanguage, math
Published: 2023-09-06 07:31:18

---
title: Creating a Fraction Converter for the Commodore 64 in Assembly Language (6510/6502) 
published: true
description: In this article, we’ll delve into the process of creating a fraction to decimal, percentage, and back converter for the Commodore 64 using Assembly language (6510/6502). This project not only provides a practical application of assembly programming skills but also allows us to explore the nostalgic charm of 80s computing. 
tags: #commodore64, #retrocomputing, #assemblylanguage,#math
# cover_image: https://cdn-images-1.medium.com/max/4100/1*01GDAkeO8A6Qg1G5WwT5wg.jpeg
# Use a ratio of 100:42 for best results.
# published_at: 2023-09-06 07:23 +0000
---
![](https://cdn-images-1.medium.com/max/4100/1*01GDAkeO8A6Qg1G5WwT5wg.jpeg)
In this article, we’ll delve into the process of creating a fraction to decimal, percentage, and back converter for the Commodore 64 using Assembly language (6510/6502). This project not only provides a practical application of assembly programming skills but also allows us to explore the nostalgic charm of 80s computing.

## Problem Statement

### Embracing the 80s Nostalgia

As we traverse through the time machine, we find ourselves in the 80s, where writing mathematical programs for the Commodore 64 is not just a hobby but part of a school course. In this article, we embark on our journey to create a fraction converter, a seemingly simple yet insightful project to sharpen our Assembly language skills.

![](https://cdn-images-1.medium.com/max/2000/1*43_KgnmVMKTntxjxMllhlw.jpeg)

This article continues the topic that I began in previous articles:

* [A Retro Adventure: Implementing an Aspect Ratio Calculator for the Commodore 64 in Multiple Programming Languages](https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m)

* [80s Time Travel: Commodore 64 Math with Square Root Approximation & Factorization using Assembly](https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg)

## Solution

## Building a BASIC Prototype

Traditionally, we commence our implementation with a prototype in BASIC. Prototype serves as a foundation, allowing us to visualize the program’s structure and overall design.

![](https://cdn-images-1.medium.com/max/2000/1*xLbP1MgCTvQ7wW4w5Ui6Rg.png)

![](https://cdn-images-1.medium.com/max/2000/1*a8BBfmd24uoubFBbXLHsKg.png)

![](https://cdn-images-1.medium.com/max/2000/1*kFoubZ6r7KHa715r1uTzSQ.png)

Two noteworthy aspects of the prototype include:

* Menu Implementation: We determine menu options.

* Exponent Calculation: Utilizing the length of textual number representation to compute the exponent.

## Transitioning to Assembly Language

Having covered numerous details in previous articles, we will focus on the high-level logic of our Assembly solution, along with the innovative approaches we’ve adopted.

## Menu Handling

After the screen setup and tooltip display, the menu display function takes centre stage as the program’s initial function. This function efficiently displays menu items and handles user input. If the user enters an invalid option, the program gracefully ignores it. Subsequently, it invokes the relevant procedure based on the user’s input.

    main:
            jsr     prepare_screen
            jsr     main_usage
    menu:
            jsr     show_menu
    wait_for_continue:
            jsr     getin
            beq     wait_for_continue
            cmp     #q_sym
            beq     go_to_exit
            cmp     #one_sym
            beq     handle_decimal
            cmp     #two_sym
            beq     handle_fraction
            cmp     #three_sym
            beq     handle_percent
            jsr     clearscreen
            jmp     menu
    handle_decimal:
            jsr     decimal_handler
            jmp     continue_or_exit
    handle_fraction:
            jsr     fraction_handler
            jmp     continue_or_exit
    handle_percent:
            jsr     percent_handler
            jmp     continue_or_exit
    go_to_exit:
            jmp     restore_and_exit
    
    continue_or_exit:
            jsr     usage_at_exit
    wait_for_input:
            jsr     getin
            beq     wait_for_input
            cmp     #q_sym
            bne     continue
            jmp     restore_and_exit
    continue:
            jsr     clearscreen
            jmp     menu
    
    restore_and_exit:
            jsr     restore_screen
    
            rts

## Decimal Conversion

    decimal_handler:
            jsr     input_decimal
            jsr     cursor_blink_off
            jsr     calculate_den
            lda     #<n
            ldy     #>n
            jsr     fp_load_ram_to_fac
            lda     #<den
            ldy     #>den
            jsr     fp_mult
            ldx     #<num
            ldy     #>num
            jsr     fp_store_fac_to_ram
            lda     #<hundred
            ldy     #>hundred
            jsr     fp_load_ram_to_fac
            lda     #<n
            ldy     #>n
            jsr     fp_mult
            ldx     #<per
            ldy     #>per
            jsr     fp_store_fac_to_ram
            jsr     show_results
            rts
    
    input_decimal:
            jsr     input_decimal_prompt
            jsr     input_string_proc
            jsr     string_to_fp
            ldx     #<n
            ldy     #>n
            jsr     fp_store_fac_to_ram
            jsr     get_exponent_by_counter
            lda     #space_sym
            jsr     print_char
            lda     #new_line
            jsr     print_char
            rts

Our decimal handler routine takes a decimal as an argument and converts it into a fraction and a percentage. This routine initiates with an input procedure similar to our earlier discussion. The key difference lies in calculating the exponent based on the entered character count.

    get_exponent_by_counter:
            ldx     counter
            dex
            txa
            sta     e_counter
            lda     number_strings
            clc
            adc     counter
            sta     address
            dec     address
            lda     #<(address)
            sta     $22
            lda     #>(address)
            sta     $23
            lda     #string_length
            jsr     fp_string_to_fac
            ldx     #<e
            ldy     #>e
            jsr     fp_store_fac_to_ram
            rts

This procedure does the following:

* Decrements the counter value by one and stores the resulting value in the exponent counters.

* Loads into the accumulator the address of the beginning of the array of string representation of numbers.

* Adds to the result the counter of entered characters saved in a variable.

* Since the offset counts from 0 reduces the value by one.

* Next, the full address of the array element is loaded with an offset.

* The string at the specified address is converted to a floating point number and stored in the variable e (exponent).

The number string array looks like the following:

    number_strings:
            .text   "0"
            .byte   $0
            .text   "1"
            .byte   $0
            .text   "2"
            .byte   $0
            .text   "3"
            .byte   $0
            .text   "4"
            .byte   $0
            .text   "5"
            .byte   $0
            .text   "6"
            .byte   $0
            .text   "7"
            .byte   $0
            .text   "8"
            .byte   $0
            .text   "9"
            .byte   $0
            .text   "10"
            .byte   $0
            .text   "11"
            .byte   $0
            .text   "12"
            .byte   $0
            .text   "13"
            .byte   $0
            .text   "14"
            .byte   $0
            .text   "15"
            .byte   $0

Next, in the decimal handler, a procedure is called to calculate the denominator.

    calculate_den:
            ldx     e_counter
            dex
            beq     handle_tenth
            txa
            sta     counter
            lda     #<ten
            ldy     #>ten
            jsr     fp_load_ram_to_fac
    mult_loop:
            lda     #<ten
            ldy     #>ten
            jsr     fp_mult
            ldx     counter
            dex
            beq     end_loop
            txa
            sta     counter
            jmp     mult_loop
    end_loop:
            ldx     #<den
            ldy     #>den
            jsr     fp_store_fac_to_ram
            jmp     end_mult
    handle_tenth:
            lda     #<ten
            ldy     #>ten
            jsr     fp_load_ram_to_fac
            ldx     #<den
            ldy     #>den
            jsr     fp_store_fac_to_ram
    
    end_mult:
            rts

This routine calculates ten powered by exponent using multiplication and the e_counter value obtained in the previous routine.

Further, I get the numerator by multiplying the entered number by the denominator.
And by multiplying the entered number by 100, I get the percentage.

Next, I display the result by a separate procedure.

    show_results:
            lda     #space_sym
            jsr     print_char
            lda     #new_line
            jsr     print_char
            lda     #<result_1
            ldy     #>result_1
            jsr     print_str
            lda     #<n
            ldy     #>n
            jsr     fp_load_ram_to_fac
            jsr     fp_to_str
            jsr     print_str
            lda     #new_line
            jsr     print_char
            lda     #<result_2
            ldy     #>result_2
            jsr     print_str
            lda     #<num
            ldy     #>num
            jsr     fp_load_ram_to_fac
            jsr     fp_to_str
            jsr     print_str
            lda     #<result_3
            ldy     #>result_3
            jsr     print_str
            lda     #<den
            ldy     #>den
            jsr     fp_load_ram_to_fac
            jsr     fp_to_str
            jsr     print_str
            lda     #new_line
            jsr     print_char
            lda     #<result_4
            ldy     #>result_4
            jsr     print_str
            lda     #<per
            ldy     #>per
            jsr     fp_load_ram_to_fac
            jsr     fp_to_str
            jsr     print_str
            lda     #new_line
            jsr     print_char
            lda     #new_line
            jsr     print_char
            rts

Limitations of this implementation:

* The function only works with fractions < 1.

* Input format “.123” without leading zero.

## Fraction Processing

The fraction processor takes numerator and denominator arguments, converting them into decimals and percentages.

    fraction_handler:
            jsr     input_num_den
            jsr     cursor_blink_off
            lda     #<den
            ldy     #>den
            jsr     fp_load_ram_to_fac
            lda     #<num
            ldy     #>num
            jsr     fp_div
            ldx     #<n
            ldy     #>n
            jsr     fp_store_fac_to_ram
            lda     #<hundred
            ldy     #>hundred
            jsr     fp_load_ram_to_fac
            lda     #<n
            ldy     #>n
            jsr     fp_mult
            ldx     #<per
            ldy     #>per
            jsr     fp_store_fac_to_ram
            jsr     show_results
            rts

A decimal is obtained by dividing the numerator by the denominator.
Percentages are obtained by multiplying a decimal by 100.

## Percentage Conversion

The percentage handler takes percentage values as input and converts them into fractions and decimals.

    percent_handler:
            jsr     input_percents
            lda     #<hundred
            ldy     #>hundred
            jsr     fp_load_ram_to_fac
            lda     #<per
            ldy     #>per
            jsr     fp_div
            ldx     #<n
            ldy     #>n
            jsr     fp_store_fac_to_ram
            lda     #<per
            ldy     #>per
            jsr     fp_load_ram_to_fac
            ldx     #<num
            ldy     #>num
            jsr     fp_store_fac_to_ram
            lda     #<hundred
            ldy     #>hundred
            jsr     fp_load_ram_to_fac
            ldx     #<den
            ldy     #>den
            jsr     fp_store_fac_to_ram
            jsr     show_results
            rts

A decimal is obtained by dividing a percentage by 100.
Normal: numerator percentage entered denominator 100.

This function has a limitation: it can correct handle only whole percent.

## Conclusion

![](https://cdn-images-1.medium.com/max/2048/1*10Y7Da0W9afOUZyCHaN6UA.png)

In this journey through the Commodore 64’s mathematical realm, we’ve developed a fraction converter in assembly language. You can find the complete source code for this program [[here](https://gist.github.com/medvecky/11fda440812e529db431aadfd71c226f)].

Here is an example of execution

![](https://cdn-images-1.medium.com/max/2000/1*QQmgYuC_5vPs-W3foYM8rQ.gif)

The binary file has a size of 3220 bytes.

While school mathematics may seem basic, it provides an excellent playground for honing assembly programming skills. This project has showcased the creative possibilities that the 80s era and Commodore 64 offer.

![](https://cdn-images-1.medium.com/max/5472/1*z0AKVAvVhHB9HnyA__U8ZQ.jpeg)

As we continue this exciting journey, I invite you to stay with me for more mathematical adventures in the world of Commodore 64 programming.