<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexey Medvecky</title>
    <description>The latest articles on DEV Community by Alexey Medvecky (@medvecky).</description>
    <link>https://dev.to/medvecky</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F219734%2F738dccf9-9dc1-46a9-882e-fb740c05bc29.jpg</url>
      <title>DEV Community: Alexey Medvecky</title>
      <link>https://dev.to/medvecky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/medvecky"/>
    <language>en</language>
    <item>
      <title>Building a Fraction Calculator for the Commodore 64 in Assembly Language</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Wed, 04 Oct 2023 06:46:48 +0000</pubDate>
      <link>https://dev.to/medvecky/building-a-fraction-calculator-for-the-commodore-64-in-assembly-language-2fk0</link>
      <guid>https://dev.to/medvecky/building-a-fraction-calculator-for-the-commodore-64-in-assembly-language-2fk0</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rpqQVmD9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_jCrCqcmAj9J5I8_KYvaQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rpqQVmD9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_jCrCqcmAj9J5I8_KYvaQQ.png" alt="" width="640" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will guide you through creating a fraction calculator for the Commodore 64 using assembly language in this article. We will utilize KickAssembler, primarily its macros, to simplify the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formulating the Problem
&lt;/h2&gt;

&lt;p&gt;My journey through the 80s using the Commodore 64 to tackle mathematical problems continues. Previous parts of my journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m"&gt;A Retro Adventure: Implementing an Aspect Ratio Calculator for the Commodore 64 in Multiple Programming Languages&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg"&gt;80s Time Travel: Commodore 64 Math with Square Root Approximation &amp;amp; Factorization using Assembly&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/medvecky/creating-a-fraction-converter-for-the-commodore-64-in-assembly-language-65106502-4gbn"&gt;Creating a Fraction Converter for the Commodore 64 in Assembly Language (6510/6502&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fractions have always been a challenge for calculators, and even in the 80s, their support was limited.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1-r9OhuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AeDvUF4oWyMIsOKCR-abi5Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1-r9OhuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AeDvUF4oWyMIsOKCR-abi5Q.jpeg" alt="" width="352" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s leverage the power of the Commodore 64 to solve this mathematical puzzle.&lt;br&gt;
In this part, we’ll dive into creating a fraction calculator, a task that was particularly challenging back in the 80s. Follow along to see how I use the Commodore 64’s capabilities to overcome this challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution.
&lt;/h2&gt;

&lt;p&gt;As previously mentioned, the 6510 processor lacks support for floating-point operations, so we’ll rely on the software implementation from BASIC ROM. I’ll use KickAssembler and its macro capabilities to expedite the development process, a luxury that may not have been available with assemblers of the 80s.&lt;br&gt;
The most commonly used macros for arithmetic operations and a macro for modulo division will be essential components of our solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0WPVqCR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2976/1%2A5NGtYls7J5n8n-v-GlYsLg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0WPVqCR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2976/1%2A5NGtYls7J5n8n-v-GlYsLg.png" alt="" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oOmYtcQf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AsqF8GFdYAb4qA8ogCXIt2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oOmYtcQf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AsqF8GFdYAb4qA8ogCXIt2w.png" alt="" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source file, complete with macro definitions and constants, is in this [&lt;a href="https://gist.github.com/medvecky/0c5e063f79aa05972b18f4da61e056d8"&gt;link to git gist&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;The program begins by displaying and processing menu selections, where the active use of macros becomes apparent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JhpYTDxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2A_tKW7RLVd9koDLMqDZrXCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JhpYTDxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2A_tKW7RLVd9koDLMqDZrXCQ.png" alt="" width="800" height="1237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--euZERCWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AC9zpEaZcH387kIRqSjwrdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--euZERCWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AC9zpEaZcH387kIRqSjwrdA.png" alt="" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Entering a String Representation of a Number
&lt;/h3&gt;

&lt;p&gt;In this project, I’ve revamped the routine for the string representation of numbers, ensuring it processes only valid characters for our program. This includes the numbers 0 to 9, “-”, “return”, and “del”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8YF0mcw1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AcwNN2DrK6Hdnk3e53v8Htw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8YF0mcw1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AcwNN2DrK6Hdnk3e53v8Htw.png" alt="" width="800" height="1101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, in addition to the exact comparison based on the zero flag, a comparison of “more” and “less” is used based on the carry flag.&lt;br&gt;
 This level of detail highlights the need for a deep understanding of the processor’s operation. It’s moments like these that make me love it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fraction Simplification and Result Display
&lt;/h3&gt;

&lt;p&gt;Simplifying a fraction is the core routine we’ve implemented first because other routines rely on it. The key to simplifying fractions is finding the greatest common divisor (GCD), which we accomplish using the Euclidean algorithm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GPw3jRE0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AMSd1Gf3ciguFoAB844RnZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GPw3jRE0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AMSd1Gf3ciguFoAB844RnZQ.png" alt="" width="400" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LGMQZScm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AMB4ALCob6VgYffOjOl4Ryg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LGMQZScm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AMB4ALCob6VgYffOjOl4Ryg.png" alt="" width="800" height="875"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simplification function handles several steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4HGw62r5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AM5_hvA4Z7hm4JJGKDUmUHQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4HGw62r5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AM5_hvA4Z7hm4JJGKDUmUHQ.png" alt="" width="800" height="1101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The routine receives arguments from the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The routine checks whether the denominator is zero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The routine copies them and passes them to the GCD routine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The routine divides the numerator and denominator by the GCD result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The routine outputs the result with the following function :&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8HYtOakt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AaJl90lWrKBTPuyYsy_FarQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8HYtOakt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AaJl90lWrKBTPuyYsy_FarQ.png" alt="" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Check whether the fraction is proper or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If improper, convert it to mixed:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9sVhZ1uv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_00GDCmMKRRjvEECyFwLGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9sVhZ1uv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_00GDCmMKRRjvEECyFwLGw.png" alt="" width="586" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zpync4di--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AJ75MrwFFpc755ZV1WeIOfQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zpync4di--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AJ75MrwFFpc755ZV1WeIOfQ.png" alt="" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prints the result of the transformation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TKQOBeUt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ApngujHw46YIQ4gerQAb7JQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TKQOBeUt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ApngujHw46YIQ4gerQAb7JQ.png" alt="" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Converting a Mixed Fraction to an Improper Fraction
&lt;/h3&gt;

&lt;p&gt;Our program also supports converting mixed fractions to improper fractions using a well-defined algorithm. The implementation details are provided there:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g3OR-Hjs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_YYduflwMa21xsAnjPXqhQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g3OR-Hjs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_YYduflwMa21xsAnjPXqhQ.png" alt="" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kEOw8PoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ApjtNadv1_UjZ98-h8jdghQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kEOw8PoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ApjtNadv1_UjZ98-h8jdghQ.png" alt="" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiplying and Dividing Fractions
&lt;/h3&gt;

&lt;p&gt;Multiplication and division of fractions are relatively straightforward operations, each with its dedicated function:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v5e_kMI---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3200/1%2Adwi-GB1Fq1--Z4SAg7rZ-A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v5e_kMI---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3200/1%2Adwi-GB1Fq1--Z4SAg7rZ-A.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2pge7_Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ALjiakW7WGZhNkGJJBPyA2A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2pge7_Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2ALjiakW7WGZhNkGJJBPyA2A.png" alt="" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dX-4kiJA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A5VXcIdTaEND7mORBZ_h2uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dX-4kiJA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A5VXcIdTaEND7mORBZ_h2uw.png" alt="" width="596" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--doN7Evoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AeXONun-pgn6k8fuOnHUM3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--doN7Evoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AeXONun-pgn6k8fuOnHUM3w.png" alt="" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding and Subtracting Fractions
&lt;/h3&gt;

&lt;p&gt;Adding and subtracting fractions are more complex due to the need to find a common denominator. We’ve tackled this challenge by implementing a casting operation based on GCD, enabling us to perform addition and subtraction efficiently.&lt;/p&gt;

&lt;p&gt;The casting operation is done using the following formula:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_t_Cn6V---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AKa-2b-enzVyDaid5QtZONw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_t_Cn6V---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AKa-2b-enzVyDaid5QtZONw.png" alt="" width="551" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is implemented with the following code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eqfe-BGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AJu5lvE-Y1HfdQ-JIDpD6yQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eqfe-BGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AJu5lvE-Y1HfdQ-JIDpD6yQ.png" alt="" width="800" height="1214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next happens in the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Entering the numerator and denominator of both fractions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Denominators are checked for zero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Denominators are passed as arguments to the GCD routine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The common denominator and multipliers for the numerators are found based on the resulting GCD.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fractions are reduced to a common denominator.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the casting function is ready, addition and subtraction are implemented by this code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FjjDzru2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5000/1%2AMfxYvvzK30I9TkmaN2vA3w.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FjjDzru2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5000/1%2AMfxYvvzK30I9TkmaN2vA3w.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8IiNNwE_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AYcWEWa0XVL2QOARSNeVi3Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8IiNNwE_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2AYcWEWa0XVL2QOARSNeVi3Q.png" alt="" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--myEs9Re9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5000/1%2A9VNsQSD7sbtXigtriBsRmg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--myEs9Re9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5000/1%2A9VNsQSD7sbtXigtriBsRmg.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OTRkM6w5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2A3-6LJWQTnVxS2pyIPVfx7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OTRkM6w5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2688/1%2A3-6LJWQTnVxS2pyIPVfx7g.png" alt="" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The final executable file is 8322 bytes in size, which may seem significant for a calculator, but future optimization is possible.&lt;/p&gt;

&lt;p&gt;The program works as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NwOe0sPy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AGzMDurtYhZ1sh-fZQJ01Vg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NwOe0sPy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AGzMDurtYhZ1sh-fZQJ01Vg.gif" alt="" width="600" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The complete source code can be found here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Main: [&lt;a href="https://gist.github.com/medvecky/e1fd9f9658489a295b91e93187e4885a"&gt;link to gist&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subroutines: [&lt;a href="https://gist.github.com/medvecky/01f090aef633d32ec54f5565c2a6d301"&gt;link to gist&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Definitions: [&lt;a href="https://gist.github.com/medvecky/0c5e063f79aa05972b18f4da61e056d8"&gt;link to gist&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data: [&lt;a href="https://gist.github.com/medvecky/51b4b3c8b98a96db6baae862b6dd6304"&gt;link to gist&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This program not only serves as a powerful tool but also brings back memories of school mathematics. I’ve thoroughly enjoyed this journey into the 80s and plan to continue exploring the capabilities of the Commodore 64 for mathematical challenges. If you’re interested, stay tuned for more adventures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s_gGCbCa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2Ak7pSZIioQgpW3VSsQJMkkQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s_gGCbCa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2Ak7pSZIioQgpW3VSsQJMkkQ.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this endeavor, I’ve deviated from the norm using macros, which greatly expedited development and made the process more enjoyable. I’ve created a tool I missed during my school days, and it’s a testament to the power of the Commodore 64. Join me in this journey through the 80s, where we continue to harness the capabilities of this remarkable machine for mathematical purposes.&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>assemblylanguage</category>
      <category>math</category>
    </item>
    <item>
      <title>Creating a Fraction Converter for the Commodore 64 in Assembly Language (6510/6502)</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Wed, 06 Sep 2023 07:31:18 +0000</pubDate>
      <link>https://dev.to/medvecky/creating-a-fraction-converter-for-the-commodore-64-in-assembly-language-65106502-4gbn</link>
      <guid>https://dev.to/medvecky/creating-a-fraction-converter-for-the-commodore-64-in-assembly-language-65106502-4gbn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cqYAP1cJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4100/1%2A01GDAkeO8A6Qg1G5WwT5wg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cqYAP1cJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4100/1%2A01GDAkeO8A6Qg1G5WwT5wg.jpeg" alt="" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Embracing the 80s Nostalgia
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BARt_eqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A43_KgnmVMKTntxjxMllhlw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BARt_eqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A43_KgnmVMKTntxjxMllhlw.jpeg" alt="" width="600" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article continues the topic that I began in previous articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m"&gt;A Retro Adventure: Implementing an Aspect Ratio Calculator for the Commodore 64 in Multiple Programming Languages&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg"&gt;80s Time Travel: Commodore 64 Math with Square Root Approximation &amp;amp; Factorization using Assembly&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Building a BASIC Prototype
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6GAMkTx7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AxLbP1MgCTvQ7wW4w5Ui6Rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6GAMkTx7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AxLbP1MgCTvQ7wW4w5Ui6Rg.png" alt="" width="727" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SH_1cVCD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aa8BBfmd24uoubFBbXLHsKg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SH_1cVCD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aa8BBfmd24uoubFBbXLHsKg.png" alt="" width="726" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jLRP6WaK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AkFoubZ6r7KHa715r1uTzSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jLRP6WaK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AkFoubZ6r7KHa715r1uTzSQ.png" alt="" width="724" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two noteworthy aspects of the prototype include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Menu Implementation: We determine menu options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exponent Calculation: Utilizing the length of textual number representation to compute the exponent.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Transitioning to Assembly Language
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Menu Handling
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Decimal Conversion
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decimal_handler:
        jsr     input_decimal
        jsr     cursor_blink_off
        jsr     calculate_den
        lda     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_mult
        ldx     #&amp;lt;num
        ldy     #&amp;gt;num
        jsr     fp_store_fac_to_ram
        lda     #&amp;lt;hundred
        ldy     #&amp;gt;hundred
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_mult
        ldx     #&amp;lt;per
        ldy     #&amp;gt;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     #&amp;lt;n
        ldy     #&amp;gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_exponent_by_counter:
        ldx     counter
        dex
        txa
        sta     e_counter
        lda     number_strings
        clc
        adc     counter
        sta     address
        dec     address
        lda     #&amp;lt;(address)
        sta     $22
        lda     #&amp;gt;(address)
        sta     $23
        lda     #string_length
        jsr     fp_string_to_fac
        ldx     #&amp;lt;e
        ldy     #&amp;gt;e
        jsr     fp_store_fac_to_ram
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This procedure does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Decrements the counter value by one and stores the resulting value in the exponent counters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Loads into the accumulator the address of the beginning of the array of string representation of numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds to the result the counter of entered characters saved in a variable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since the offset counts from 0 reduces the value by one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, the full address of the array element is loaded with an offset.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The string at the specified address is converted to a floating point number and stored in the variable e (exponent).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The number string array looks like the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, in the decimal handler, a procedure is called to calculate the denominator.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculate_den:
        ldx     e_counter
        dex
        beq     handle_tenth
        txa
        sta     counter
        lda     #&amp;lt;ten
        ldy     #&amp;gt;ten
        jsr     fp_load_ram_to_fac
mult_loop:
        lda     #&amp;lt;ten
        ldy     #&amp;gt;ten
        jsr     fp_mult
        ldx     counter
        dex
        beq     end_loop
        txa
        sta     counter
        jmp     mult_loop
end_loop:
        ldx     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_store_fac_to_ram
        jmp     end_mult
handle_tenth:
        lda     #&amp;lt;ten
        ldy     #&amp;gt;ten
        jsr     fp_load_ram_to_fac
        ldx     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_store_fac_to_ram

end_mult:
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This routine calculates ten powered by exponent using multiplication and the e_counter value obtained in the previous routine.&lt;/p&gt;

&lt;p&gt;Further, I get the numerator by multiplying the entered number by the denominator.&lt;br&gt;
And by multiplying the entered number by 100, I get the percentage.&lt;/p&gt;

&lt;p&gt;Next, I display the result by a separate procedure.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show_results:
        lda     #space_sym
        jsr     print_char
        lda     #new_line
        jsr     print_char
        lda     #&amp;lt;result_1
        ldy     #&amp;gt;result_1
        jsr     print_str
        lda     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_load_ram_to_fac
        jsr     fp_to_str
        jsr     print_str
        lda     #new_line
        jsr     print_char
        lda     #&amp;lt;result_2
        ldy     #&amp;gt;result_2
        jsr     print_str
        lda     #&amp;lt;num
        ldy     #&amp;gt;num
        jsr     fp_load_ram_to_fac
        jsr     fp_to_str
        jsr     print_str
        lda     #&amp;lt;result_3
        ldy     #&amp;gt;result_3
        jsr     print_str
        lda     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_load_ram_to_fac
        jsr     fp_to_str
        jsr     print_str
        lda     #new_line
        jsr     print_char
        lda     #&amp;lt;result_4
        ldy     #&amp;gt;result_4
        jsr     print_str
        lda     #&amp;lt;per
        ldy     #&amp;gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Limitations of this implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The function only works with fractions &amp;lt; 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Input format “.123” without leading zero.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fraction Processing
&lt;/h2&gt;

&lt;p&gt;The fraction processor takes numerator and denominator arguments, converting them into decimals and percentages.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fraction_handler:
        jsr     input_num_den
        jsr     cursor_blink_off
        lda     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;num
        ldy     #&amp;gt;num
        jsr     fp_div
        ldx     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_store_fac_to_ram
        lda     #&amp;lt;hundred
        ldy     #&amp;gt;hundred
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_mult
        ldx     #&amp;lt;per
        ldy     #&amp;gt;per
        jsr     fp_store_fac_to_ram
        jsr     show_results
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A decimal is obtained by dividing the numerator by the denominator.&lt;br&gt;
Percentages are obtained by multiplying a decimal by 100.&lt;/p&gt;

&lt;h2&gt;
  
  
  Percentage Conversion
&lt;/h2&gt;

&lt;p&gt;The percentage handler takes percentage values as input and converts them into fractions and decimals.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;percent_handler:
        jsr     input_percents
        lda     #&amp;lt;hundred
        ldy     #&amp;gt;hundred
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;per
        ldy     #&amp;gt;per
        jsr     fp_div
        ldx     #&amp;lt;n
        ldy     #&amp;gt;n
        jsr     fp_store_fac_to_ram
        lda     #&amp;lt;per
        ldy     #&amp;gt;per
        jsr     fp_load_ram_to_fac
        ldx     #&amp;lt;num
        ldy     #&amp;gt;num
        jsr     fp_store_fac_to_ram
        lda     #&amp;lt;hundred
        ldy     #&amp;gt;hundred
        jsr     fp_load_ram_to_fac
        ldx     #&amp;lt;den
        ldy     #&amp;gt;den
        jsr     fp_store_fac_to_ram
        jsr     show_results
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A decimal is obtained by dividing a percentage by 100.&lt;br&gt;
Normal: numerator percentage entered denominator 100.&lt;/p&gt;

&lt;p&gt;This function has a limitation: it can correct handle only whole percent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2dLwR1wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A10Y7Da0W9afOUZyCHaN6UA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2dLwR1wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A10Y7Da0W9afOUZyCHaN6UA.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 [&lt;a href="https://gist.github.com/medvecky/11fda440812e529db431aadfd71c226f"&gt;here&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Here is an example of execution&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DlvDVOD6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AQQmgYuC_5vPs-W3foYM8rQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DlvDVOD6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AQQmgYuC_5vPs-W3foYM8rQ.gif" alt="" width="600" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The binary file has a size of 3220 bytes.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dVGEGfS2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5472/1%2Az0AKVAvVhHB9HnyA__U8ZQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dVGEGfS2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/5472/1%2Az0AKVAvVhHB9HnyA__U8ZQ.jpeg" alt="" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

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

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>assemblylanguage</category>
      <category>math</category>
    </item>
    <item>
      <title>Embarking on an 80s Time Travel Adventure: Commodore 64 Machine Code Programming with BASIC</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Mon, 07 Aug 2023 10:43:18 +0000</pubDate>
      <link>https://dev.to/medvecky/embarking-on-an-80s-time-travel-adventure-commodore-64-machine-code-programming-with-basic-4he7</link>
      <guid>https://dev.to/medvecky/embarking-on-an-80s-time-travel-adventure-commodore-64-machine-code-programming-with-basic-4he7</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YLyjRwvm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3200/1%2A_Q-7il1c-QPvkBVe7JANCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YLyjRwvm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3200/1%2A_Q-7il1c-QPvkBVe7JANCQ.png" alt="" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we delve into the captivating realm of Commodore 64 programming, journeying back to the 80s to uncover the art of crafting machine code using the trusty BASIC language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unveiling the Challenge
&lt;/h3&gt;

&lt;p&gt;As alluded to in a &lt;a href="https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg"&gt;prior piece&lt;/a&gt;, my quest led me to an assembly book, reigniting my quest for knowledge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SIr1zP2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AoDsCoaqk6MaIC_IFNlS8Tg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SIr1zP2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AoDsCoaqk6MaIC_IFNlS8Tg.jpeg" alt="" width="726" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing that impressed me was the ability to memorize machine codes and then call them for execution using only BASIC. While this may seem commonplace to some, it was a revelation for me. In an era where disk drives and assemblers weren’t always at hand, BASIC stood as a steadfast companion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Harnessing BASIC Magic
&lt;/h3&gt;

&lt;p&gt;To showcase BASIC’s prowess, I’ll guide you through crafting a “HELLO WORLD” program in machine code, and the method behind the magic is surprisingly simple.&lt;/p&gt;

&lt;p&gt;Key BASIC Commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PEEK(): Retrieves memory cell contents at a given address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POOKE , : Writes a value to a specific memory cell.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;READ, DATA: Creates and sequentially reads an array of data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our initial venture involves writing a character to video memory, achieved through a concise program structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LnVkVM8b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AwyTYxBn4CIAIYF3bJYyEdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LnVkVM8b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AwyTYxBn4CIAIYF3bJYyEdA.png" alt="" width="722" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The BASIC part here acts as a program loader in machine codes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Employing the READ command, we extract machine code values one by one until completion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The POKE statement diligently transfers these segments to memory, starting at address 49152 with incremental offsets.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upon completing the loop, a SYS instruction calls the stored machine code procedure, initiating execution. The machine code itself is elegantly straightforward. We inscribe character code “x” (24) into the accumulator, preserving it at the video memory’s onset (address 1024).&lt;/p&gt;

&lt;p&gt;Our exploration doesn’t halt here. The process extends to outputting entire words, data transfer from BASIC to machine code, and dynamic memory interaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l6shl0nx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A6y8iZS3iJBckdupnq8tbrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l6shl0nx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A6y8iZS3iJBckdupnq8tbrw.png" alt="" width="720" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AYq2G_Ak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AKqesFCRv7e-_bSXXKXXlAg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AYq2G_Ak--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AKqesFCRv7e-_bSXXKXXlAg.png" alt="" width="722" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can also transfer data from BASIC to the program in machine codes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---cS8jlex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ASlbw8b85-vmXHJsftvorLA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---cS8jlex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ASlbw8b85-vmXHJsftvorLA.png" alt="" width="720" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gn_RMbbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2An64QRHSOPlTxRR3ubfh7bQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gn_RMbbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2An64QRHSOPlTxRR3ubfh7bQ.png" alt="" width="720" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the letter code is requested via INPUT and then, via POKE, the resulting value is written to a specific memory cell.&lt;br&gt;
The machine code program takes data from this memory location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f5dz3yjG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AOtr95E_OjKkrefNsnG1aVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f5dz3yjG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AOtr95E_OjKkrefNsnG1aVQ.png" alt="" width="719" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is such programming in machine codes straight from BASIC.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Journey of Rediscovery
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n-i7ukiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A9DNMeb-U_5C47QKm1jSNSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n-i7ukiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A9DNMeb-U_5C47QKm1jSNSA.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reflecting on my initial tryst with BASIC on a Z80-based home computer, I’ve come to respect its capabilities anew. BASIC’s techniques seamlessly transition to assembly programming, and the language itself emerges as a potent tool, especially through the methodologies detailed in this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Continuation of an Odyssey
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m_9g5fKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AHoKiI5VcG1nBObdclOj7qQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m_9g5fKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AHoKiI5VcG1nBObdclOj7qQ.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Armed with newfound insights, I’m poised to continue my 80s odyssey. The quest persists as I delve deeper into the potential of C64 and Assembly, particularly in tackling intriguing mathematical challenges.&lt;/p&gt;

&lt;p&gt;Join me as we traverse the enthralling landscape of 80s programming, unearthing gems from the past to enrich our present journey.&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>assemblylanguage</category>
      <category>basic</category>
    </item>
    <item>
      <title>80s Time Travel: Commodore 64 Math with Square Root Approximation &amp; Factorization using Assembly</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Mon, 07 Aug 2023 09:51:00 +0000</pubDate>
      <link>https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg</link>
      <guid>https://dev.to/medvecky/80s-time-travel-commodore-64-math-with-square-root-approximation-factorization-using-assembly-4chg</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vm7Cxw-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANEhfFYxNCCCYMxS9CAgnGA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vm7Cxw-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANEhfFYxNCCCYMxS9CAgnGA.jpeg" alt="" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I embark on a nostalgic journey back to the 80s, using the Commodore 64 (C64) to solve mathematical challenges. Building on the success of my &lt;a href="https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m"&gt;previous article&lt;/a&gt;, where I tackled proportion problems, I now dive into creating a calculator capable of computing approximate square roots and factoring them into factors using Assembly language.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Formulation of the Problem.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I was inspired to push the boundaries further after successfully solving proportion problems in my last article. I aimed to harness the power of the C64 to develop a calculator that efficiently calculates square roots, a frequently demanded operation in various mathematical domains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JcHreeAa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AE7rfKJiTBTiJr8_z1CgTyQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JcHreeAa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AE7rfKJiTBTiJr8_z1CgTyQ.png" alt="" width="512" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, I sought to enable the factorization of square roots, a more accurate solution, which proves valuable in fields like trigonometry, signal processing, electrical circuit calculations, and optimization calculations. Function for calculation of square root numerical approximate value have every calculator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XbZc2Lyd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AenhYNQWMNBYym8WnDprJ4Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XbZc2Lyd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AenhYNQWMNBYym8WnDprJ4Q.gif" alt="" width="259" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To factorize the square root into factors, special tools are already needed. So the corresponding program for C64 is handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Algorithm&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core algorithm I adopted is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Obtain the root of the number ‘x’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find an approximate answer using the built-in BASIC SQR function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For factorization in the loop, do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Traverse integers from 1 to ‘x’ and identify the maximum number whose square is a factor of ‘x’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine the second multiplier as ‘x’ divided by the square of the maximum factor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prepare answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first part of the answer is the square root of the square of the maximum factor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second part lies under the square root and is the second factor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation on BASIC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On BASIC, the program takes shape as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cbxcWz8q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFGGv4AO88iVtjVv9Gx4n9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cbxcWz8q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFGGv4AO88iVtjVv9Gx4n9A.png" alt="" width="717" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SvhDDbl9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AP4BqgI957e1dvSYbR4q6wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SvhDDbl9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AP4BqgI957e1dvSYbR4q6wg.png" alt="" width="723" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To simulate the modulo operation in BASIC, I used the following construction: A % B = A — INT(A / B) * B. Modulo is used to determine whether a number is a factor of the argument or not. The result of running the program looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XRTzpM4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0w1I2gUSgpjqRLrrlonR2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XRTzpM4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0w1I2gUSgpjqRLrrlonR2g.png" alt="" width="726" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cycle is already noticeable in the delay between the approximate answer and the factorized one, even on big numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation On Assembly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building on the procedures developed in my &lt;a href="https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m"&gt;previous article&lt;/a&gt;, I focused on the primary algorithm implementation.&lt;/p&gt;

&lt;p&gt;The implementation is as follows:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        *= $1000
main:
        jsr     prepare_screen
        jsr     main_usage

wait_for_continue:
        jsr     getin
 beq     wait_for_continue
        cmp     #q_sym
        beq     go_to_exit
        jmp     get_args
go_to_exit:
        jmp     restore_and_exit

get_args:
        jsr     get_argument
        jsr     init_variables

        //calculate and print sqr(argument)
        lda     #&amp;lt;argument
        ldy     #&amp;gt;argument
        jsr     fp_load_ram_to_fac
        jsr     fp_sqr
        ldx     #&amp;lt;ul
        ldy     #&amp;gt;ul
        jsr     fp_store_fac_to_ram
        jsr     fp_fac_print

        //ul = int(sqr(argument)) + 1
        lda     #&amp;lt;ul
        ldy     #&amp;gt;ul
        jsr     fp_load_ram_to_fac
        jsr     fp_int
        lda     #&amp;lt;one
        ldy     #&amp;gt;one
        jsr     fp_add
        ldx     #&amp;lt;ul
        ldy     #&amp;gt;ul
        jsr     fp_store_fac_to_ram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The first block involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Preparing screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieving the argument from the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initializing variables with a value of 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calculating the approximate square root value using the BASIC function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting the upper limit for the factorization loop.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subsequent block features the factorization loop:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;loop:   // for mf=1 to ul

        //x = mf^2
        lda     #&amp;lt;mf
        ldy     #&amp;gt;mf
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;mf
        ldy     #&amp;gt;mf
        jsr     fp_mult
        ldx     #&amp;lt;x
        ldy     #&amp;gt;x
        jsr     fp_store_fac_to_ram

        //y = int(argument) / int(x)
        lda     #&amp;lt;argument
        ldy     #&amp;gt;argument 
        jsr     fp_load_ram_to_fac
        jsr     fp_int
        ldx     #&amp;lt;y
        ldy     #&amp;gt;y
        jsr     fp_store_fac_to_ram

        lda     #&amp;lt;x
        ldy     #&amp;gt;x
        jsr     fp_load_ram_to_fac
        jsr     fp_int 

        lda     #&amp;lt;y
        ldy     #&amp;gt;y
        jsr     fp_div
        ldx     #&amp;lt;y
        ldy     #&amp;gt;y
        jsr     fp_store_fac_to_ram

        //if argument - int(y) * x &amp;lt;&amp;gt; 0 goto next iteration
        lda     #&amp;lt;y
        ldy     #&amp;gt;y
        jsr     fp_load_ram_to_fac
        jsr     fp_int
        lda     #&amp;lt;x
        ldy     #&amp;gt;x
        jsr     fp_mult
        lda     #&amp;lt;argument
        ldy     #&amp;gt;argument
        jsr     fp_subst
        lda     #&amp;lt;zero
        ldy     #&amp;gt;zero
        jsr     fp_cmp
        cmp     #$0
        bne     not_factor

        lda     #&amp;lt;x
        ldy     #&amp;gt;x
        jsr     fp_load_ram_to_fac
        ldx     #&amp;lt;maxf
        ldy     #&amp;gt;maxf
        jsr     fp_store_fac_to_ram        
not_factor:
        lda     #&amp;lt;mf
        ldy     #&amp;gt;mf
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;one
        ldy     #&amp;gt;one
        jsr     fp_add
        ldx     #&amp;lt;mf
        ldy     #&amp;gt;mf
        jsr     fp_store_fac_to_ram
        lda     #&amp;lt;ul
        ldy     #&amp;gt;ul
        jsr     fp_cmp
        cmp     #$1
        bne     go_to_loop
        jmp     end_loop
go_to_loop:
        jmp     loop

end_loop:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Assembly code mirrors the functionality of the corresponding BASIC loop. Floating-point number comparisons are conducted using a BASIC function, and the results in register A are tested using a simple comparison operator.&lt;/p&gt;

&lt;p&gt;Then I calculate and store both parts of the result.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //sr = int(sqr(maxf))
        lda     #&amp;lt;maxf
        ldy     #&amp;gt;maxf
        jsr     fp_load_ram_to_fac
        jsr     fp_sqr
        jsr     fp_int
        ldx     #&amp;lt;sr
        ldy     #&amp;gt;sr
        jsr     fp_store_fac_to_ram 

        //of = int(argument)/int(maxf)
        lda     #&amp;lt;argument
        ldy     #&amp;gt;argument
        jsr     fp_load_ram_to_fac
        jsr     fp_int
        ldx     #&amp;lt;of
        ldy     #&amp;gt;of
        jsr     fp_store_fac_to_ram

        lda     #&amp;lt;maxf
        ldy     #&amp;gt;maxf
        jsr     fp_load_ram_to_fac
        jsr     fp_int
        lda     #&amp;lt;of
        ldy     #&amp;gt;of
        jsr     fp_div
        jsr     fp_int
        ldx     #&amp;lt;of
        ldy     #&amp;gt;of
        jsr     fp_store_fac_to_ram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Results output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//result output
        lda     #&amp;lt;sr
        ldy     #&amp;gt;sr
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;one
        ldy     #&amp;gt;one
        jsr     fp_cmp
        cmp     #$1
        bne     next_part
        lda     #&amp;lt;sr
        ldy     #&amp;gt;sr
        jsr     fp_load_ram_to_fac
        jsr     fp_to_str
        jsr     print_str
next_part:
        lda     #&amp;lt;of
        ldy     #&amp;gt;of
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;one
        ldy     #&amp;gt;one
        jsr     fp_cmp
        cmp     #$1
        bne     end_of_output
        lda     #&amp;lt;result_string_1
        ldy     #&amp;gt;result_string_1
        jsr     print_str
        lda     #&amp;lt;of
        ldy     #&amp;gt;of
        jsr     fp_load_ram_to_fac
        jsr     fp_to_str
        jsr     print_str
        lda     #right_p_sym
        jsr     print_char
end_of_output:
        lda     #new_line
        jsr     print_char
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here I’m ignoring the part of the result which equals one because it doesn’t matter when factoring.&lt;/p&gt;

&lt;p&gt;Here is the output of the program:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1ymL2u2C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AXNAVz9Bza7WTkHfd8U7YYQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1ymL2u2C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AXNAVz9Bza7WTkHfd8U7YYQ.png" alt="" width="718" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assembly program compiles to 2864 byte binary file. The delay is also visible in large numbers but much less than in the BASIC implementation.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://gist.github.com/medvecky/6160dc2b92cc4f632008bc9748b756df"&gt;complete source code&lt;/a&gt; of the program.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QyuGRryz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AnFQ9u1_QzusGgWRVBE8Xdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QyuGRryz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AnFQ9u1_QzusGgWRVBE8Xdw.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While BASIC provides valuable tools for solving simple mathematical problems, the ability to call BASIC functions from Assembly code saves effort and allows for compact, fast programs.&lt;/p&gt;

&lt;p&gt;My journey through the 80s, reviving mathematical programming on the C64, has been enjoyable and rewarding. To further improve my skills, I aim to delve into assembly 6510 (6502) and find relevant books to fill any knowledge gaps.&lt;/p&gt;

&lt;p&gt;As I continue my exploration of mathematical programs for C64, I invite you to stay tuned for my future posts. The excitement of revisiting the 80s has given me ample reasons not to return to our time.&lt;/p&gt;

&lt;p&gt;Until next time, warm regards and happy programming!&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>math</category>
      <category>assemblylanguage</category>
    </item>
    <item>
      <title>A Retro Adventure: Implementing an Aspect Ratio Calculator for the Commodore 64 in Multiple Programming Languages</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Mon, 07 Aug 2023 09:38:58 +0000</pubDate>
      <link>https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m</link>
      <guid>https://dev.to/medvecky/a-retro-adventure-implementing-an-aspect-ratio-calculator-for-the-commodore-64-in-multiple-programming-languages-349m</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jgi4U-zS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4372/1%2AY4MnZOySXUe2G8wqx1Y0TQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jgi4U-zS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4372/1%2AY4MnZOySXUe2G8wqx1Y0TQ.jpeg" alt="" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I explore the possibility of using C64 to solve mathematical problems. Using the example of solving the proportion, I will show how BASIC, C, and MOS 6510 (6502) Assembly can be used for these purposes using the BASIC functions for the floating point operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do I want to do?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PJ8iEGlc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A-MTuEAQaERdVUMMFl_ng2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PJ8iEGlc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A-MTuEAQaERdVUMMFl_ng2g.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And so I continue my journey through time in the 80s. I’m trying to settle down here and use C64 as a tool for study and work.&lt;/p&gt;

&lt;p&gt;In past articles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-c-2kj3"&gt;Time-Travelling to Commodore 64: Hello World Program on C.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-assembly-296b"&gt;Time-Travelling to Commodore 64: Hello World Program on Assembly.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I learned a little about the tools I can use: BASIC, Assembly, C. Contrary to my expectations, C could have been better here than BASIC and Assembly. It’s time to do something more exciting and valuable than just “Hello, world”.&lt;/p&gt;

&lt;p&gt;Problems from the school mathematics course for solving proportions are best suited for this. The formula for equivalent ratios looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--62bMC2Ta--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AbylbQPOFf_TvEY3nLgrPuA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--62bMC2Ta--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AbylbQPOFf_TvEY3nLgrPuA.png" alt="" width="792" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given three knowns and one unknown, the unknown can continuously be computed. For example, in the formula n1 / d1 = n2 / d2, if d1 is unknown, it can be calculated as follows d1 = n1 * d2 / n2.&lt;/p&gt;

&lt;p&gt;The proportions are simple enough to solve without mastering programming tools. At the same time, the proportion calculator is quite a helpful thing.&lt;/p&gt;

&lt;p&gt;It can be used for various calculations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The ratio in proportions in the preparation of recipes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conversion from one unit of measurement to another&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Percent-related problems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;etc&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  First Approach
&lt;/h2&gt;

&lt;p&gt;I made the prototype in BASIC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WpXA1zte--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AMivunO5DHN4wbEu3WCuyAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WpXA1zte--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AMivunO5DHN4wbEu3WCuyAQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HhSh70gR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AzRe-KqrYILeyYi7LMM7qCw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HhSh70gR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AzRe-KqrYILeyYi7LMM7qCw.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Works well enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O1Sx1stx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFLVMb5zog_3vuajONKx8iA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O1Sx1stx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFLVMb5zog_3vuajONKx8iA.gif" alt="" width="600" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is implemented following algorithm. nj&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I read the parameters and used 0 to sign that the parameter is unknown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using branching, I select the desired formula for the calculation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I bring out the result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I offer the choice to continue the work or exit the program.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now I want to make a more compact program version with my design.&lt;/p&gt;

&lt;p&gt;Since I still feel unsure about the MOS 6510(6502) Assembly, I decide to try C again on C64.&lt;/p&gt;

&lt;p&gt;Of course, I can also do the screen design in BASIC, but I need to be more active to remember all this again. Still, I want to use more advanced tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big fail with C.
&lt;/h2&gt;

&lt;p&gt;And so the implementation in C.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void setUpScreen( void )
{
   clrscr();
   defaultBGColor = bgcolor( COLOR_BLACK );
   defaultBorderColor = bordercolor( COLOR_BLACK );
   defaultTextColor = textcolor( COLOR_GREEN );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I started by setting screen parameters using library functions. Functions have an exemplary implementation. When selecting new parameters, they return the original ones. It is very convenient to save them to restore the settings when I exit the program.&lt;/p&gt;

&lt;p&gt;Usage hint output function&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void usage( void )
{
   cputsxy( 12, 0, "RATIO CALCULATOR" );
   cputsxy( 12, 2, "N1/D1 = N2/D2" );
   gotoxy( 0, 4 );
   puts( "Input ratio pramams by prompt" );
   puts( "Press any key to continue" );
   puts( "or q to exit" );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here I use both library functions for C64 and standard C functions for text output and positioning.&lt;/p&gt;

&lt;p&gt;Argument input function.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void getArgs( int * n1, int * d1, int * n2, int * d2 )
{
   cursor( 1 );
   printf( "%s? ", "n1 (zero if unknown)" );
   scanf( "%d", n1 );
   printf( "%s? ", "d1 (zero if unknown)" );
   scanf( "%d", d1 );
   printf( "%s? ", "n2 (zero if unknown)" );
   scanf( "%d", n2 );
   printf( "%s? ", "d2 (zero if unknown)" );
   scanf( "%d", d2 );
   cursor( 0 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I use a library function for C64 to turn the cursor blinking on and off.&lt;/p&gt;

&lt;p&gt;Response Calculation Function&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char getAnswer( int n1, int d1, int n2, int d2 )
{
   int answer = 0;

   if ( n2 == 0 )
   {
      answer = d2 * n1 / d1;
      printf( "n2 = %d\n", answer );    
   }
   else if ( d2 == 0 )
   {
      answer = n2 * d1 / n1;
      printf( "d2 = %d\n", answer );    
   }
   else if ( n1 == 0 )
   {
      answer = d1 * n2 / d2;
      printf( "n1 = %d\n", answer );    
   }
   else if ( d1 == 0 )
   {
      answer = n1 * d2 / n2;
      printf( "d1 = %d\n", answer );    
   }
   else
   {
      puts( "Wrong params" );
   }

   puts( "Press any key to continue" );
   puts( "or q to exit" );

   return cgetc();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;An unpleasant surprise awaited me, the C compiler available does not support floating point numbers.&lt;br&gt;
This is one more point in favour of using Assembly for development under C64.&lt;/p&gt;

&lt;p&gt;In this function, I violated the principle of sole responsibility&lt;br&gt;
Because in addition to calculating the answer, the operator’s choice to continue the calculations or exit is returned here and also displays a hint.&lt;br&gt;
I’ll probably fix this in the future.&lt;/p&gt;

&lt;p&gt;The last function I wrote is to restore the screen state before exiting the program.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void resetDefaultScreen( void )
{
   clrscr();
   bgcolor( defaultBGColor );
   bordercolor( defaultBorderColor );
   textcolor( defaultTextColor );
   * ( char *  ) 0xD018 = 0x15;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here I use the same functions as in the screen settings.&lt;br&gt;
I also use the system variable setting.&lt;br&gt;
This command is equivalent to POKE 53272.21, which sets the output mode of letters to uppercase.&lt;/p&gt;

&lt;p&gt;The main function looks like this.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int main ( void )
{
   int n1 = 0;
   int d1 = 0;
   int n2 = 0;
   int d2 = 0;
   unsigned character = 0;
   int answer = 0;

   setUpScreen();

   usage();
   character = cgetc();

   while ( character != 'q' )
   {
      getArgs( &amp;amp;n1, &amp;amp;d1, &amp;amp;n2, &amp;amp;d2 );
      character = getAnswer( n1, d1, n2, d2 );

      clrscr();
   }

   resetDefaultScreen();

   return EXIT_SUCCESS;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It uses the C64 library function to clear the screen.&lt;/p&gt;

&lt;p&gt;Here is a working example&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qI27qZRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AehTXUXjd1TEIwRGZfWakyQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qI27qZRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AehTXUXjd1TEIwRGZfWakyQ.gif" alt="" width="600" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/medvecky/020dca571c25b844de123f1b5af55f70"&gt;The complete source code of the program is available here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The executable file turned out to be 7167 bytes.&lt;/p&gt;

&lt;p&gt;Calculating the proportions of the possibility of a floating point operation could be more helpful. So I take up the implementation in Assembly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assembly Saves the World.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VohsGyhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A0TCFMKSbPgA6BeIxg_z5gA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VohsGyhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2A0TCFMKSbPgA6BeIxg_z5gA.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ll start as before with the preparation of the screen.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prepare_screen:
// set gren text color
        lda     #5
        sta     text_color
        jsr     clearscreen

// set border and background black
        lda     #$00
        sta     border
        sta     background
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, the same thing happens as in the analogue in C. I write to the system variables at the desired addresses and values through the accumulator.&lt;/p&gt;

&lt;p&gt;Here is the main hint.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main_usage:
        ldx     #$00
        ldy     #$0a
        jsr     set_cursor

        lda     #&amp;lt;usage_1
        ldy     #&amp;gt;usage_1
        jsr     print_str

        lda     #new_line
        jsr     print_char
        jsr     print_char

        lda     #&amp;lt;usage_1_1
        ldy     #&amp;gt;usage_1_1
        jsr     print_str

        lda     #new_line
        jsr     print_char
        jsr     print_char

        lda     #&amp;lt;usage_2
        ldy     #&amp;gt;usage_2
        jsr     print_str

        lda     #new_line
        jsr     print_char

        lda     #&amp;lt;usage_3
        ldy     #&amp;gt;usage_3
        jsr     print_str
        lda     #new_line
        jsr     print_char
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here I use three kernal functions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;set_cursor (0xE50C) Arguments are passed through X Y registers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;print_char (0xFFD2) character code for output must be in the accumulator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;print_str(0xAB1E) in register A low byte of row address in Y high byte&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The string must end with ‘\0’ as in this example.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;usage_1:
        .text   "RATIOS CALCULATOR"
        .byte   $00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next comes a piece of code responsible for waiting and processing the user’s reaction.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wait_for_continue:
        jsr     getin
        beq     wait_for_continue
        cmp     #q_sym
        beq     restore_and_exit_jmp
        jmp     get_args

restore_and_exit_jmp:
        jmp     restore_and_exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To read a character into the accumulator, I use the getin(0xFFE4) function&lt;/p&gt;

&lt;p&gt;Three checks follow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If the accumulator is 0, the user did not enter anything. Repeat the entry procedure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a user selects “Q “ as an exit, I proceed to the appropriate procedure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If any other character, I jump to calculations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Calculations begin with the collection of arguments&lt;/p&gt;

&lt;p&gt;The following function performs them.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_arguments:
        jsr     input_n1_proc
        jsr     input_d1_proc
        jsr     input_n2_proc
        jsr     input_d2_proc
        jsr     cursor_blink_off
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Functions run similar functions for receiving each argument and, in the end, call the function to turn off the cursor blinking.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cursor_blink_off:
        lda     $00cf
        beq     cursor_blink_off
        lda     #$01
        sta     $cc
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;According to the state of the system variable 0x00CF, this function waits for the moment when the cursor will go out and then writing one to the system variable 0x00CC disables the cursor blinking.&lt;/p&gt;

&lt;p&gt;The function for getting an argument is already more complicated.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input_n1_proc:
        jsr     input_n1_prompt
        jsr     input_string_proc
        jsr     string_to_fp
        ldx     #&amp;lt;n1
        ldy     #&amp;gt;n1
        jsr     fp_store_fac_to_ram
        lda     #space_sym
        jsr     print_char
        lda     #new_line
        jsr     print_char
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The input_prompt function prints an input prompt to the screen as described.&lt;br&gt;
Next, the operation of reading the string representation of the argument from the keyboard starts.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input_string_proc:
        ldy #$00
        ldx     #$00
        lda     #$00
        sta     counter
input_get:
        jsr     getin
        beq     input_get
        cmp     #$0d
        beq     input_string_end
        cmp     #$14
        bne     increase_counter
        jsr     print_char
        ldx     counter
        dex
        stx     counter
        lda     #$00
        sta     input_string,x
        jmp     input_get
increase_counter:
        ldx     counter
        sta     input_string,x
        jsr     print_char
        inx
        stx     counter
        cpx     #string_length
        bne input_get
input_string_end:
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this function, I first reset the accumulator, all index registers, and the counter.&lt;/p&gt;

&lt;p&gt;I call the get_in function&lt;/p&gt;

&lt;p&gt;Next, I check for the following cases&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If the user presses return, the input is complete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the user has entered backspace, I display the backspace character. Showing this character causes the cursor to jump back one character visually. Next, I decrease the counter of entered characters and delete the previously entered character in the buffer by writing zero in its place. After that, I return to the beginning of the procedure.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When entering any other character, I perform the following actions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I store the character in the buffer with an offset equal to the counter of the entered characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I display the character on the screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I increment the counter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I check the counter. If the maximum is reached, then an entry is terminated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, I proceed to the processing of the next entered character.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Further, the function input_n1_proc continues to be executed.&lt;br&gt;
After the input of the string is completed, I use the following function&lt;br&gt;
to convert the string to float.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string_to_fp:
        lda     #&amp;lt;input_string
        sta     $22
        lda     #&amp;gt;input_string
        sta     $23
        lda     #string_length
        jsr     fp_string_to_fac 
        jsr     clear_input_string
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To do this, I use the existing BASIC function that can be called through the address (0xB7B5). As arguments at addresses 0x22 0x23, I need to place the low and high byte of the address of the buffer with the string, in register A, the length of the entered string. Next, I call the conversion function. The function puts the received number in the FAC, which is located at the following addresses in the RAM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Address 97/$61 is the exponent byte.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Addresses 98–101/$62–$65 hold the four-byte (32 bit) mantissa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Address 102/$66 stores the sign in its most significant bit; 0 for positive, $FF (-1) for negative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Address 112/$70 contains rounding bits for intermediate calculations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I clear the buffer by writing 0 to it.&lt;/p&gt;

&lt;p&gt;After that, I write the number from the FAC to a variable using the function (0xBBD4) . Funcion needs address of 5 bytes variable as argument where will store value from FAC.&lt;/p&gt;

&lt;p&gt;One important point some of operations with FAC corupt data in FAC. Fro example function for print FAC to scree. That’s why need in first store data from FAC before any operation with FAC.&lt;/p&gt;

&lt;p&gt;Next, I output space to overwrite the courses and translate the line.&lt;/p&gt;

&lt;p&gt;Similarly, I get and save all the necessary variables.&lt;/p&gt;

&lt;p&gt;Next block of code&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//check n1 
        lda     #&amp;lt;n1
        ldy     #&amp;gt;n1
        jsr     fp_load_ram_to_fac
        lda     #&amp;lt;fp_zero
        ldy     #&amp;gt;fp_zero
        jsr     fp_cmp
        cmp     #$00
        beq     solve_for_n1

..................................

        lda     #&amp;lt;wrong_params
        ldy     #&amp;gt;wrong_params
        jsr     print_str
        lda     #new_line
        jsr     print_char

        jmp     wait_to_exit

solve_for_n1:
        jsr     solve_for_n1_proc
        jmp     wait_to_exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The entered variables will be checked for 0 one by one using the floating point comparison function (0xBC55B), which compares the FAC with the number in memory at A Y.&lt;br&gt;
After the unknown variable is found, control is transferred to the corresponding calculation function.&lt;br&gt;
If the operator has not entered an unknown value, an error message and a suggestion to exit the program or continue calculations are displayed.&lt;/p&gt;

&lt;p&gt;The calculation function looks like this.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solve_for_n1_proc:
        lda     #&amp;lt;d1
        ldy     #&amp;gt;d1
        jsr     fp_load_ram_to_fac

        lda     #&amp;lt;n2
        ldy     #&amp;gt;n2
        jsr     fp_mult

        ldx     #&amp;lt;n2
        ldy     #&amp;gt;n2
        jsr     fp_store_fac_to_ram

        lda     #&amp;lt;d2
        ldy     #&amp;gt;d2
        jsr     fp_load_ram_to_fac

        lda     #&amp;lt;n2
        ldy     #&amp;gt;n2
        jsr     fp_div

        ldx     #&amp;lt;n1
        ldy     #&amp;gt;n1
        jsr     fp_store_fac_to_ram

        jsr     result_n1_prompt

        lda     #&amp;lt;n1
        ldy     #&amp;gt;n1
        jsr     fp_load_ram_to_fac

        jsr     fp_fac_print
        lda     #new_line
        jsr     print_char
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The function performs multiplication and division of floating point numbers using the functions provided by BASIC. Further, using the previously described function, the result is output.&lt;/p&gt;

&lt;p&gt;The final block of the program.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wait_to_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     get_args
restore_and_exit:
        jsr     restore_screen

        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Displays a hint prompting a user to continue computing or exit.&lt;br&gt;
Depending on the user’s choice, respectively returns to the parameter input stage or restores the initial state of the screen and exits to BASIC.&lt;/p&gt;

&lt;p&gt;Screen recovery.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;estore_screen:
// restore border and background colors
        lda     #$0f6
        sta     background
        lda     #$fe
        sta     border

// restore text color
        lda     #$e
        sta     text_color
        jsr     clearscreen

// restore text mode
        lda     #$015
        sta     $d018
        rts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The program works like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iIJgDzMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AImda523BAbkO6GnOdA2bBg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iIJgDzMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AImda523BAbkO6GnOdA2bBg.gif" alt="" width="600" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/medvecky/72ef713b03d53d8973d2fb26fc5719d5"&gt;The full text of the program is available here&lt;/a&gt;&lt;br&gt;
The executable file size is 3137 bytes. &lt;br&gt;
Approximately two times less than the option on C.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final conclusion of today’s journey.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5qAN4ROQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AoFlUuS_hGn2A34l3C36HVA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5qAN4ROQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AoFlUuS_hGn2A34l3C36HVA.jpeg" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What conclusions can be drawn from the work done?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;C in the realities of C64 in the 80s is not as good as in our time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BASIC is quite good and has extensive features, but it needs to be faster, and programs come out large.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assembly, on the one hand, looks like a leader. Learning and using it is easier than it seemed, mainly if you use the ready-made functions that kernal and BASIC provide. But the development speed still needs to be improved, especially if you write something more voluminous.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you look closely at Assembly, learning BASIC seems more valid now. BASIC is just fine for writing program prototypes before they are implemented in Assembly.&lt;/p&gt;

&lt;p&gt;It was a good day in the 80s. I am more and more immersed in the realities of programming at this time. When you try something with your hands, many mental distortions dissipate.&lt;/p&gt;

&lt;p&gt;I like it here more and more, and I’m still in no hurry to return. Thank you for being a part of this journey.&lt;/p&gt;

&lt;p&gt;I hope it was at least fun.&lt;/p&gt;

&lt;p&gt;Warm regards.&lt;/p&gt;

&lt;p&gt;Stay tuned for my next posts.&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>math</category>
      <category>assemblylanguage</category>
    </item>
    <item>
      <title>Time-Travelling to Commodore 64: Hello World Program on Assembly.</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Mon, 07 Aug 2023 08:13:31 +0000</pubDate>
      <link>https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-assembly-296b</link>
      <guid>https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-assembly-296b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--57Ut8iHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A3EiDFNItVQwExZIUDxX4fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--57Ut8iHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A3EiDFNItVQwExZIUDxX4fg.png" alt="" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I continue my journey into the 80s, which I started in the &lt;a href="https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-c-2kj3"&gt;previous article&lt;/a&gt; and will further explore the programming tools that the Commodore 64 offered in those years. In this article, I will look at the possibilities of programming on assembly using Turbo Macro Pro.&lt;/p&gt;

&lt;p&gt;After experimenting with C, described in the &lt;a href="https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-c-2kj3"&gt;last article&lt;/a&gt;, I concluded that there are more convenient tools for c64.&lt;br&gt;
Therefore, the following tool is assembly.&lt;/p&gt;

&lt;p&gt;To start programming on assembly, I must understand the MOS 65xx processor instructions, the C64 memory map, and how the peek and poke operators work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HguWatVb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2782/1%2AaRgKtcmMcFzfFUChfHQmTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HguWatVb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2782/1%2AaRgKtcmMcFzfFUChfHQmTA.png" alt="" width="800" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, I need a tool to compile assembly code. I used Turbo Macro Pro. Turbo Macro Pro has good documentation and can highlight syntax errors almost immediately.&lt;/p&gt;

&lt;p&gt;I can load TMP from the disk with the familiar ‘LOAD’ command. Run the TMP command with ‘sys 32768’; this command transfers control to the code at the specified address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_EZHYSs5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_3MNqwKRbq_TfqoMxW3lhA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_EZHYSs5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A_3MNqwKRbq_TfqoMxW3lhA.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After starting, I got into the code editor.&lt;br&gt;
The editor is pretty handy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjVkGx-n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0gKsacjzuEDnTuN8_i28dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjVkGx-n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0gKsacjzuEDnTuN8_i28dg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will try to write a “hello world” program.&lt;br&gt;
To do this, I need to place a line with text in memory and display it in video memory.&lt;br&gt;
For this, I am using the following code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TAxNezAK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A1xc9EVaTbFYxeC9mqnQ7mQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TAxNezAK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A1xc9EVaTbFYxeC9mqnQ7mQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I am using 0x01000 as an entry point&lt;br&gt;
I initialize register x to zero.&lt;br&gt;
In the loop, I will perform the following actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I read a character from a string at index x into the accumulator.&lt;/li&gt;
&lt;li&gt;I store the contents of the accumulator at the beginning of the video memory with an offset x.&lt;/li&gt;
&lt;li&gt;I increment x&lt;/li&gt;
&lt;li&gt;Checking if x is not equal to the length of the string
If not, the cycle repeats.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After the end of the program, the control goes back to the BASIC, and the program’s results are not visible.&lt;br&gt;
Therefore, after the output of the line, I add an infinite loop.&lt;/p&gt;

&lt;p&gt;To start the program, I need to press the back arrow key, which locates in the top left corner. It is a command button. After it, I need to enter the command for the editor.&lt;br&gt;
I enter a “3” after the command button to compile the program. Appears a screen with the results of the compilation. The ‘s’ button runs the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VfY3hIlN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0zsi6HBaRUQ-gzc6lJav3Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VfY3hIlN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0zsi6HBaRUQ-gzc6lJav3Q.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My string appeared at the beginning of the screen on top of everything already on screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oLjNEEYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AYhLtc7KCXznjZAwls0zFsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oLjNEEYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AYhLtc7KCXznjZAwls0zFsA.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not very pretty. I need to clear the screen.&lt;br&gt;
To do this, I stop the program with the key combination run/stop + restore and return to BASIC. With the sys 32768 commands, I return to TMP, where my source code persists, which is convenient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dyRzzzqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AqxDo2OM6JLI8xeI53RPXGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dyRzzzqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AqxDo2OM6JLI8xeI53RPXGw.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is screen cleaning.&lt;br&gt;
For this, I have added the following code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xDFmhCHn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aky3qQLmxN0wPQ1NyHQSgpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xDFmhCHn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aky3qQLmxN0wPQ1NyHQSgpg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Writes 0 to register x&lt;/li&gt;
&lt;li&gt;Writes 0x020 ( space code ) to the accumulator&lt;/li&gt;
&lt;li&gt;Then, in a loop:&lt;/li&gt;
&lt;li&gt;Writes the accumulator’s value to a region of video memory that starts at addresses 0x0400 0x0500 0x0600 0x0700 with an x offset.&lt;/li&gt;
&lt;li&gt;Decreases x by one.&lt;/li&gt;
&lt;li&gt;In this case, the ‘bne’ operator will work when x not equals 0.
Accordingly, the code will write spaces to all specified areas with an offset from FF to 0.
That is the entire visible area of the screen.
Now the output looks like this.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RCvqxMBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApoXP16eoPKQ0o6eka6ZnqQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RCvqxMBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApoXP16eoPKQ0o6eka6ZnqQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems better, but I want to display the inscription in the middle of the screen. Everything is simple here. I change the starting address of the output to ‘0x054e’, in which the text will be approximately in the centre.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BWXvU8ox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABweA2d8lFoMjPUoDkxPN1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BWXvU8ox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABweA2d8lFoMjPUoDkxPN1A.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a new output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p_QmDAev--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A53fZl6piijgi8Kchvsy6Bw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p_QmDAev--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A53fZl6piijgi8Kchvsy6Bw.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also wanted to make the output green like in classic terminals.&lt;br&gt;
After studying the documentation, I realized I needed to write the code for the colour, 5 for green, into memory at 0x0286.&lt;br&gt;
And also, call the system program to update the screen.&lt;br&gt;
Here is the relevant code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1CnyyEP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AezPu4ohxjree17qQuJ5l6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1CnyyEP4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AezPu4ohxjree17qQuJ5l6g.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Execution result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--49_ootX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFZogAryzIFt_OTLcV25jWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--49_ootX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFZogAryzIFt_OTLcV25jWg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything is beautiful now. I decided to compile an independent program and run it from BASIC. According to the documentation, I again enter the command mode to do this. Only instead of 3 I need to press 5.&lt;br&gt;
TMP prompts me to enter the name of the executable file. Also, I saved the source for this. I used the s command. To run the finished program, I load it and run it with the sys command 4096 (0x0100 ). This address that I set as the entry point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--clDfSAse--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A11g9U0Z8dtLFcxVDiDvvGQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--clDfSAse--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A11g9U0Z8dtLFcxVDiDvvGQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Something went wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hhNtYFzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFHNO1TKhjI8U2tioOFxYig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hhNtYFzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFHNO1TKhjI8U2tioOFxYig.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I understand from the documentation, after the output, I need to restore the screen mode to LOWER / UPPER CASE&lt;br&gt;
to do this, I need to write value 0x017 at the address 0x0d018 analogue&lt;br&gt;
poke 53272,23&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BWXvU8ox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABweA2d8lFoMjPUoDkxPN1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BWXvU8ox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABweA2d8lFoMjPUoDkxPN1A.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YWNDkipo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0PZrRsI5EOOP8T48APeA5A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YWNDkipo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A0PZrRsI5EOOP8T48APeA5A.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks better, but I want a strict black background. To do this, according to the documentation, I need to write 0 (black code) into memory at addresses 0x0d020 (for the border) and 0x0d021 (for the background)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lda #$00
sta $d020
sta $d021
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now It looks as I wish.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--49_ootX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFZogAryzIFt_OTLcV25jWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--49_ootX9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AFZogAryzIFt_OTLcV25jWg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yeah, now I have prepared the workbench for assembly programming.&lt;/p&gt;

&lt;p&gt;What can be the conclusion?&lt;br&gt;
On the one hand, programming on assembly requires a lot of immersion in the architecture of mos 65xx processors, understanding the C64 memory map and knowledge of its system routines.&lt;br&gt;
It is easier than it looks at the first time. &lt;br&gt;
On the other hand, I get faster and more convenient compilation instead of constant disk juggling, as in Power C.&lt;/p&gt;

&lt;p&gt;It is clear why the programmers of the 80s on the Commodore 64 preferred assembly.&lt;/p&gt;

&lt;p&gt;I’m still in no hurry to return from the 80s.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gSlV7OAS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AUwhGOKJYKwjKHNZjPPDL5Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gSlV7OAS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AUwhGOKJYKwjKHNZjPPDL5Q.png" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for being a part of this journey.&lt;br&gt;
I hope it was at least fun.&lt;br&gt;
Warm regards.&lt;br&gt;
Stay tuned for my next posts.&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>retrocomputing</category>
      <category>retroprogramming</category>
      <category>assemblylanguage</category>
    </item>
    <item>
      <title>Time-Travelling to Commodore 64: Hello World Program on C.</title>
      <dc:creator>Alexey Medvecky</dc:creator>
      <pubDate>Mon, 07 Aug 2023 06:14:19 +0000</pubDate>
      <link>https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-c-2kj3</link>
      <guid>https://dev.to/medvecky/time-travelling-to-commodore-64-hello-world-program-on-c-2kj3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--57Ut8iHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A3EiDFNItVQwExZIUDxX4fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--57Ut8iHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A3EiDFNItVQwExZIUDxX4fg.png" alt="" width="800" height="531"&gt;&lt;/a&gt;&lt;br&gt;
This time I will review the possibilities of programming on the Commodore 64 and try to understand how a modern programmer would feel in the realities of the mid-80s.&lt;/p&gt;

&lt;p&gt;In those years, I did not have a Commodore 64 but had a ZX Spectrum clone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nT6KSS6T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AIKUvWM9g4qkFKIsW6N4EjA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nT6KSS6T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AIKUvWM9g4qkFKIsW6N4EjA.jpeg" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There was no Internet, and there were few programming books.&lt;br&gt;
So the maximum I then did on the Spectrum was writing simple scripts in BASIC to solve problems in mathematics and physics and games like Landing on the Moon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UcFVkWh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ALtRjIXhllPPJb2YyJwD2sQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UcFVkWh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ALtRjIXhllPPJb2YyJwD2sQ.png" alt="" width="424" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Therefore, I have always been interested in the stories of my acquaintances who did more exciting things on 8-bit computers. I wanted to do it myself using the knowledge now available.&lt;/p&gt;

&lt;p&gt;I'm starting an experiment. I'm in my mid-80s; I have a Commdore64 with a disk drive, some set of programs and books, there is no Internet, but the grass is greener, the sun is brighter, and the girls are more beautiful, and there is also a lot of time for experiments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yhU9zTYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AnJ-eFZR-RxkgIs8QE1svvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yhU9zTYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AnJ-eFZR-RxkgIs8QE1svvw.png" alt="" width="495" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the beginning, I needed to understand what the Commodore 64 offered for programming and try to write a "hello world" program.&lt;/p&gt;

&lt;p&gt;The first thing that catches my eye is a different layout of special characters on the keyboard and a tiny resolution by modern standards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x7RnlVz_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4088/1%2ASLiokUEYoXxPLxUzmPn65w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x7RnlVz_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4088/1%2ASLiokUEYoXxPLxUzmPn65w.png" alt="" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I get used to the layout, it's a matter of time, but how the developers in these conditions viewed and debugged extended programs; so far, the question is.&lt;/p&gt;

&lt;p&gt;After turning on the C64, BASIC is launched. This is a programming environment and a shell with essential OS functions.&lt;br&gt;
I can save and delete files to disk and make some adjustments by changing the values of variables in memory using the poke statement.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// There is a command examples
SAVE "MY_PRG",8
LOAD "MY_PRG",8,1
LIST
RUN
POKE 53280,1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since BASIC starts immediately, let's try to do something about it, for example, "Hello world".&lt;br&gt;
In BASIC, everything is simple. Compared to Spectrum, the C64 has a more advanced ability to edit text within the screen.&lt;br&gt;
The first program looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wlMByY1a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AR1Pbb7Tp3Dp9Z-etMTCpXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wlMByY1a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AR1Pbb7Tp3Dp9Z-etMTCpXA.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ik8hhMcd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AVXQcyjKSJ3-53TV-kZ43Cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ik8hhMcd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AVXQcyjKSJ3-53TV-kZ43Cw.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can save a program to disk and then load it back.&lt;br&gt;
I figured out the BASIC, but there are too few tools here.&lt;/p&gt;

&lt;p&gt;What else can I try? Assembly is still tricky because I need to learn a set of commands.&lt;br&gt;
The C should be better here because I know it.&lt;br&gt;
I have a set of two floppy disks for C with the "power c" compiler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rbGSHVT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AM9u0vB-uophqZhM5a0cZJg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rbGSHVT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AM9u0vB-uophqZhM5a0cZJg.jpeg" alt="" width="300" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a short study of the manual, I started the shell.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EYybYuRI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Abasau7MYoWOHQsbhOu8Ncg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EYybYuRI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Abasau7MYoWOHQsbhOu8Ncg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mVlvqIJj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AvaIdlAihg2ve-WW7SeeLlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mVlvqIJj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AvaIdlAihg2ve-WW7SeeLlg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compared to BASIC, it's much more comfortable; at least there are several Unix-like commands like 'ls' and 'rm'.&lt;/p&gt;

&lt;p&gt;I launch the editor and enter the program's text. The non-standard layout still interferes, but it's not so scary anymore. Curly braces are placed on the "+" and "-" keys. I know it from the manual.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// command to launch editor with spell checking

ced
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--he7JZbuJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUjNcI_6AqqyGJqZIBI_Stw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--he7JZbuJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUjNcI_6AqqyGJqZIBI_Stw.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have entered the program. The separate command performs a syntax check&lt;br&gt;
Command mode is invoked by key (Hi VIM)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// to enter command mode press [run/stop] button
// command to start spelcheking 

check

//command to exit to shell

quit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From the same mode, we save the program's text to disk just to the same disk where power c is located. It's worth saving to a separate floppy disk for more complex projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J7DZdGxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aas73FEFFp_F3bldCWN32zQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J7DZdGxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Aas73FEFFp_F3bldCWN32zQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I exit the editor and start the compiler. Here is a suggestion to use separate source and object file disks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qvtiviTu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AT2xNWNRtcP-Vl4Hi86qUAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qvtiviTu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AT2xNWNRtcP-Vl4Hi86qUAQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I run the linker to create a simple shell executable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QUYx6gn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUwMXiyk6k37F7BNdxuxwFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QUYx6gn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AUwMXiyk6k37F7BNdxuxwFQ.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I enter a special character — arrow to top. At this stage, I need to change the disk to the second one because that is where the necessary libraries are located. After the prompt, change the disk back. Save the executable file. Everything is ready. Now I can run my program as a shell script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ao2TDHj1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ADL33CS6gN9rJ1oCuvJBuKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ao2TDHj1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ADL33CS6gN9rJ1oCuvJBuKA.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, the programmer is almost a DJ here, but if the project is large and the source and object files are stored on separate disks…..&lt;/p&gt;

&lt;p&gt;This most straightforward program's compilation, linking and loading time could be more encouraging. I had time to read the manual during the process, but what will happen on a more advanced project?&lt;/p&gt;

&lt;p&gt;I add the key -s to the link command, repeat the linking process, and get an independent executable file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9BtYn6NX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABuqm9xv8dDbNmvV9A_v7IA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9BtYn6NX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ABuqm9xv8dDbNmvV9A_v7IA.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This executable I can now load and run from BASIC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Df9Udp_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AezLYMbXmJa-DlmZLrZOeEg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Df9Udp_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AezLYMbXmJa-DlmZLrZOeEg.png" alt="" width="384" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inscription became an upper case for some reason, but this looks like some feature. I will deal with this later.&lt;/p&gt;

&lt;p&gt;The "Hello World" program is not just a string output. It means &lt;br&gt;
the developer knows how to use the editor, compiler and linker. These days when it's all done automatically or in one command, it doesn't seem very relevant, but on C64, "hello world" is still an important step to start programming.&lt;/p&gt;

&lt;p&gt;The first step is done, now I still need to make hello world in Assembly, and then it will be possible to say that I have all the tools in my hands.&lt;/p&gt;

&lt;p&gt;I don't want to return from the 80s, so I'll rest here and take a walk.&lt;/p&gt;

&lt;p&gt;Thank you for being a part of this journey.&lt;br&gt;
I hope it was at least fun.&lt;br&gt;
Warm regards.&lt;br&gt;
Stay tuned for my next posts.&lt;/p&gt;

</description>
      <category>commodore64</category>
      <category>c64</category>
      <category>retrocomputing</category>
      <category>retroprogramming</category>
    </item>
  </channel>
</rss>
