I am new in assembler programming and want to get the 6502 to count from 0 to 65536 and want some help to the code. I must use 2 bytes (word), but the problem is that the INC command only increments one byte.
2 Answers
I am new in assembler programming
A hint for the future
Most modern computers (there are only few exceptions) work with bytes. This means: These computers work in a base-256 system.
The same mathematical rules that apply to the decimal system also apply to all other systems - including base-256.
Whenever you want to perform some operation in assembly, you should first think about how the corresponding problem in decimal system looks like and how you would solve it.
to count to 65536 ... I must use 2 bytes (word), but the problem is that the INC command only increments one byte.
The corresponding problem in decimal system is:
I must count from 0 to 100. However, in school I only learned which decimal digit follows another digit (e.g. 6 is followed by 7) but they didn't teach me which 2-digit number follows another 2-digit one (e.g. 86 is followed by 87).
Now let's look at the decimal problem:
To count from 0 to 99, you can use two digits; counting to 100 already requires three digits.
You would probably solve the problem the following way:
- You start with
000
- You would count up by one the following way:
- You would replace the last digit by the following one.
Example: If the current value is086
, you would replace the6
by a7
so you end up in087
. - If the last digit is
9
, you would replace the9
by a0
and replace the middle digit.
Example: If the number is079
, you would first replace the last digit:070
and because you replaced the last digit by a0
, you also replace the middle digit:080
- If you replace the middle digit by a
0
, you also replace the first digit: Performing the steps described above,099
first becomes090
, then000
, then100
- You would replace the last digit by the following one.
- As soon as you performed the last step, your task is done because you reached the value 100.
Assembly language:
Let's look at the steps done in decimal system again and compare it to the steps we have to do in assembly language:
- Decimal: To count from 0 to 99, you can use two digits; counting to 100 already requires three digits.
Assembly: Counting from 0 to 65535 can be done using two bytes; 65536 already requires three bytes. - Decimal: You start with
000
Assembly: You have to use some instructions (such asLDA
andSTA
) to ensure that the three (or two) bytes initially have the value 0. - You would count up by one the following way:
- Decimal: You would replace the last digit by the following one.
Assembly: You use theINC
instruction to increment (this means: count up) the last byte. - Decimal: If the last digit is
9
, you would replace the9
by a0
and ...
Assembly: TheINC
instruction will count from 255 to 0; this is like counting from 9 to 0 in decimal system. TheINC
instruction will set theZ
flag when it counts from 255 to 0; it will clear theZ
flag if it did not do so.
Using theBNE
instruction you can jump to some instruction if theZ
flag is not set. This means you can skip some instructions that are only executed ifINC
counted from 255 to 0. (Or you can jump "backwards" to the start of some loop if you didn't count from 255 to 0 ...) - Decimal: ... and replace the middle digit.
Assembly: You apply theINC
instruction to the middle byte. - Decimal: If you replace the middle digit by a
0
...
Assembly: This means: TheINC
instruction that you applied to the middle byte has replaced 255 by 0 and therefore set theZ
flag!
- Decimal: You would replace the last digit by the following one.
- Decimal: As soon as you performed the last step, your task is done because you reached the value 100.
Assembly: The same is true for counting to 65536 in base-256 system.
Some note:
6502 has three registers: A
, X
and Y
. For this reason, you can also count in the registers (INX
, INY
...) instead of counting in memory as long as your largest number is less than 2^24.
We know from grade school and base 10 that say
19
+ 1
====
you use a carry, to carry values into the next power of 10
1
19
+ 1
====
0
9+1 = 0 carry the 1.
This works for all bases. Now also understand zero, there is an implied zero before you started
0
19
+ 1
====
as the carry in to that first digit.
10
19
+ 1
====
20
is what it looks like completed. But what if my paper was so skinny or I wrote my numbers so big I could not fit but one column per page.
the ones column
10
9
+1
====
0
the tens column would need to bring the carry in from the ones column
01
1
+0
====
2
implied zero for the second operand and also recognize this operation has a carry out as well, it is zero so we do not care, then we can take the two operations resulting in a 0 and a 2 and combine them in our head to understand the result to be 20. 19+1 = 20
base 2 or base 16 are no different
1FFF
+ 0001
=======
the least significant byte, no carry in
110
FF
+ 01
=======
00
then the remaining bytes for as many bytes wide as you desire, need to add the carry in from the prior operation
11
1F
+ 00
=======
20
giving the result 0x2000 using one byte at a time math.
So depending on how much you want to add per loop you can look at the instructions that do that, paying careful attention to if the carry flag is modified as an output for that operation. Then look for an add operation that adds in that carry flag in order to cascade. Note that it takes four bytes for this in some form the two for the top and the two for the bottom operand, although you may find shortcuts.
likewise if you want to stop at 65535 (We assume you made a typo there), then you need to think about how to do a compare with 0xFFFF a byte at a time and keep looping if both bytes are not the final value.
Or are you actually supposed to count 65536 times from 0x0000 to 0x0000? Same difference except where do you do the loop test? In C would it be a while() or a do...while(), for example.
ADC
instruction. – Michael