Saturday, March 30, 2019

Multi-byte Numbers

Just because the 6502 is an 8-bit processor does not mean that it is limited to dealing with numbers that are larger than 8-bits. You can have as many bits as your memory will support though dealing with larger numbers does add a lot of work that the program has to do. The purpose of the carry flag is for dealing with multi-byte numbers. The big issue is that you can only work with 8 bits at a time of the number. While you can use the x and y registers as temporary holders for parts of the larger number, you most likely will want to store that number somewhere in memory.

There are many ways of storing a multi-byte number but the two most common formats are big-endian and little-endian in reference to  Gulliver's Travels where there were groups of people who fought over whether it was proper to crack a soft-boiled egg from the big end (the big-endians) or the little end (little-endians). CPU makers have been having a similar fight with the decision being should the high order byte be stored in the lower address followed by the lower order byte(s) which we call big-endian or should we do this with the lowest order byte first followed by the higher bytes.


The 6502 is considered to be a little-endian architecture due to the way memory addresses are stored. This is not necessarily how you need to store multi-byte numbers in memory, but this tends to be the convention for 6502 programmers. However, since the registers are only 8 bits, it really does not matter what convention you use as long as you are consistent. Here is a sample of doing a 16-bit addition.

JMP test

; Big Endian variables
BE_NumberAHi: .BYTE $3
BE_NumberALo: .BYTE $E8
BE_NumberBHi: .BYTE $3
BE_NumberBLo: .BYTE $E8

; Little Endian Variables
LE_NumberALo: .BYTE $E8
LE_NumberAHi: .BYTE $3
LE_NumberBLo: .BYTE $E8
LE_NumberBHi: .BYTE $3

test:
; Big endian A = A + B
LDA BE_NumberALo
CLC
ADC BE_NumberBLo ; add low btye
STA BE_NumberALo
LDA BE_NumberAHi ; add high byte
ADC BE_NumberBHi ; using carry from prev add.
STA BE_NumberAHi
; Little endian A = A + B
LDA LE_NumberALo
CLC
ADC LE_NumberBLo ; add low btye
STA LE_NumberALo
LDA LE_NumberAHi 
ADC LE_NumberBHi ; add high byte
STA LE_NumberAHi ; using carry from prev add.
NOP
BRK

As you can see there is no real difference which order you store the data in but this is not the case with processors that have larger registers. Multi-byte math is done by taking advantage of the carry flag as the ADC instruction will add an additional 1 to the result of the add if the carry flag is set. This is why you clear the carry flag before adding the low byte, you then add the higher bytes. Note that you can have as many bytes as you want in your number as long as you continue to chain the bytes.

The same procedure for multi-byte addition works for rotation and subtraction, though with subtraction you need to set the carry flag (SEC) not clear it. We will be seeing a demo of multi-byte rotation next fortnight when I implement my 8x16-bit multiplier.

No comments:

Post a Comment