Wednesday, April 4, 2018

Decimal Flag and Binary Coded Decimal


The decimal flag is what the 6502 processor uses to determine if the add instruction ADC and subtract instructions SBC should be done using binary arithmetic or using binary coded decimal. Binary coded decimal breaks each byte into two nibbles. A nibble is four bits. The following image shows how this works.



This means that the number 42 would be represented in binary as 0100 0010 which if proper binary was used would be 66 in decimal. Accidently having decimal mode active when working with numbers can result in unexpected results which is why you will often see one of the first instructions in an Atari 2600 program being CLD. The NES does not have this problem as they use a custom version of the 6502 which does not support decimal mode.

Decimal mode is a legacy mode which is not really used anymore. Some programs do use decimal mode as it makes printing out things like a score easier as you can easily mask off the and shift the bits so you are dealing with one nibble at a time and that nibble is in the range of 0 through 9. Really nice to have for humans writing machine language but with libraries and compiled languages it’s use was not that high. The 6502 does support it so I will need to deal with it. There are only 4 instructions that care about decimal mode and those are SED, CLD, ADC, and SBC. The math instructions will be covered in a later article when I get to the math instructions.

CLDCLear Decimal mode
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Implied
216
$D8
1
2
Flags affected: D
Usage: Use right away in program to make sure not in decimal mode otherwise you will get really weird results if you use ADC or SBC instructions.
Test Code:
     SED
     CLD
     BRK
; Expect D = 0

Implementation:
m->run {
                m.state.flags = m.state.flags and (255 xor DECIMAL_FLAG)
}

SEDSEt Decimal Mode
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Implied
248
$F8
1
2
Flags affected: D
Usage: When you want to manipulate binary coded decimal numbers, use this command to enable decimal mode and use the CLD command when you are done (unless all numbers are in BCD)
Test Code:
     CLD
     SED
     BRK
; Expect D = 1

Implementation:
m->run {
     m.state.flags = m.state.flags or DECIMAL_FLAG
}




No comments:

Post a Comment