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.
CLD – CLear 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)
}
SED – SEt 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