Classic Computer Magazine Archive COMPUTE! ISSUE 54 / NOVEMBER 1984 / PAGE 134

All About The Status Register

Part 2

Louis F. Sander

Beginning machine language programmers are often confused by the 6502's status register, a collection of eight bits which act as status flags. Part 1, published last month, briefly described the function of each flag. Part 2 picks up with a more detailed explanation and includes a sample program for the Commodore 64, PET/CBM, Apple, and Atari.

Last month's short description of the 6502's eight-bit processor status register and the seven status flags it contains may have cleared some mystery away, but it surely wasn't comprehensive. That sort of description is found in most machine language programming books, to which you are now referred, and which will be much easier to understand once you've mastered what is presented here. Let's gain that mastery by running a simple test program, using a machine language monitor to observe its effects on the status register.

6502 Monitors

A monitor is nothing more than a machine language program that makes it easier to work with other ML programs, and there are many, many different monitors available for the 6502. Sometimes monitors are called debuggers. PET/CBMs and Apples have simple monitors built into their ROMs, while Ataris have one in the Assembler Editor cartridge. Commodore 64s can use "Supermon64," a program that appeared in COMPUTE! (January 1983). Our test program works identically on all those machines, but since their monitors are somewhat dissimilar, we'll show the screen dialogue for each one.

The monitor is a wonderful tool for the beginning ML programmer, and if you've dabbled with ML, you've at least used it to examine memory locations and to save ML programs on tape or disk. I used mine for those things for many months, but never paid much attention to the registers display. That's the line of labeled numbers the monitor sometimes prints on the screen, and it looks like this on Commodore machines:

PCIRQSRACXRYRSP
000572E830005E04F8

(If you have an Apple or Atari, please follow the Commodore explanation anyway. Your monitor is only slightly different.)

PC shows the address in the 6502's program counter, which is nothing more than the address of the next instruction to be executed. Because of various quirks, monitor PC displays are not all alike. Supermon64 and the Atari monitor show the address of the BRK instruction which activated them; the Commodore monitor shows the address one byte after the BRK; and the Apple shows the address two bytes after the BRK. Some monitors don't label the address, but all of them display it.

IRQ (not shown on many monitors) gives the so-called interrupt vector, a very important address, but one beyond the scope of our interest here.

SR gives the contents of the processor status register, expressed in hexadecimal form. (The label is P in Apple/Atari, but what it displays is exactly, absolutely, positively identical in all the monitors.) People with 6502's in their cerebral cortices may be able to determine individual flag statuses from a hex display, but it's a burdensome interpretation for the rest of us. Who can figure out whether $FB means the Z flag is set or clear? Not me, I can guarantee you. The table is a handy guide for interpreting that byte. With it, you can tell at a glance which flags are set or cleared in a given status byte, and just what each flag means. And that ability can be a golden key to better machine language programming.

AC, XR, and YR show the contents of the accumulator, X, and Y registers, respectively, at the moment the monitor was activated. They're labeled A, X, and Y in some monitors, but mean the same thing, regardless of the label.

SP (or S) gives the value of the stack pointer, which is yet another useful value that's beyond our present scope. The value will vary from time to time and from machine to machine.

Stepping Through Flags

Now that you've seen a description of the register display, plus that handy table, let's use them to experiment with the important flags. Our experiment will have the dual benefit of making us more fluent in ML, and giving us practice using the register display.

The program at the end of this article is an instructive, but do-nothing, ML program that occupies an innocuous corner of memory. From left to right, each line shows a memory address, the bytes held by it and maybe its upward neighbor, and the mnemonic for the instruction that those bytes represent. The program's first seven lines set all the 6502's flags and registers to zero, then break to the monitor, where we can review their status.

Single, Simple Operations

The rest of the program is a series of single, simple operations, each followed by a break to the monitor. We're about to go through them one by one, and see what happens to the negative, break, zero, and carry flags. We'll leave V, D, and I for another day, for the reasons previously mentioned.

Figure 1: Apple Screen Dialogue

Step 1To activate the monitor, type CALL – 151, then press RETURN.]CALL-151
Step 2Put the program into memory by making these entries exactly as shown. Press RETURN at the end of each line.* 3300 : D8 18 A9 00 AA A8 C9 FF
* 3308 : 00 A9 80 00 A9 7F 00 A9
* 3310 : 00 00 A9 FF 00 69 01 00
* 3318 : 69 01 00 C9 02 00 00 00
Step 3Check your work by entering this command and comparing your screen display with the program* 3300L
Step 4Type the G command, then press RETURN. When this line appears, return to the text.* 3300G
330A- A = 00 X = 00 Y = 00 P = 30 S = F0
Step 5This and the following steps are identical to Step 4, except for the numbers entered and displayed.* 3309G 330D- A = 80 X = 00 Y = 00 P =B0 S = EE
Step 6As above.* 330CG
3310- A = 7F X = 00 Y = 00 P = 30 S = EC
Step 7As above.* 330FG 3313- A = 00 X = 00 Y = 00 P = 32 S = EA
Step 8As above.* 3312G 3316- A = FF X = 00 Y = 00 P = B0 S = E8
Step 9As above.* 3315G 3319- A = 00 X = 00 Y = 00 P = 33 S = E6
Step AAs above.* 3318G 330C- A = 02 X = 00 Y = 00 P = 30 S = E4
Step BAs above. This is the last step in our demonstration.*331BG 331F- A = 02 X = 00 Y = 00 P = 33 S = E2

Figures 1–3, the different versions for PET/CBM, Apple, and Atari, will be used to track our demonstration. Find the version which applies to you, and follow it as you read on.

Steps 1–3. Our first step will be to put the ML demo program into memory. Do it now, by carefully following Steps 1, 2, and 3 of the appropriate version of Figure 1, 2, or 3. If you've never worked with ML before, don't worry—the process is easy, and we'll take you through it step by step. When you finish Step 3, come back here for further instructions.

At the end of Step 3, the monitor should still be active, and your screen should be showing you its distinctive monitor prompt. You're now ready to run the ML demo program, which you do by executing your monitor's G command.

Figure 2: Atari Screen Dialogue

Step 1To activate the monitor, insert the Assembler Editor cartridge, and answer the EDIT prompt by typing BUG, then pressing RETURN.DEBUG C3300<DBDEBUG C<00DEBUG C<01
DEBUG C<18DEBUG C<A9DEBUG C<00
DEBUG C<A9DEBUG C<7FDEBUG C<69
DEBUG C<00DEBUG C<00DEBUG C<01
DEBUG C<AADEBUG C<A9DEBUG C<00
Step 2Put the program into memory by making entries exactly as shown. Press RETURN at the end of each line.DEBUG C<A8DEBUG C<00DEBUG C<C9
DEBUG C<C9DEBUG C<00DEBUG C<02
DEBUG C<FFDEBUG C<A9DEBUG C<00
DEBUG C<00DEBUG C<FFDEBUG C<00
DEBUG C<A9DEBUG C<00DEBUG C<00
DEBUG C<80DEBUG C<69DEBUG C<00
DEBUG
Step 3Check your work by entering this command and comparing your screen display with the one shown.D 3300, 331F
3300 D8 18 A9 00 AA A8 C9 FF
3308 00 A9 80 00 A9 7F 00 A9
3310 00 00 A9 FF 00 69 01 00
3318 69 01 00 C9 02 00 00 00
DEBUG
Step 4Type the G 3300 command, then press RETURN. When DEBUG appears, return to the text.G 3300 3308 DEBUGA = 00 X = 00 Y = 00 P = 30 S = 00
Step 5This and the following steps are identical to Step 4, except for the numbers entered and displayed.G 3309 330B DEBUG A = 80 X = 00 Y = 00 P = B0 S = 00
Step 6As above.G 330C 330E DEBUGA = 7F X = 00 Y = 00 P = 30 S = 00
Step 7As above.G 330F 3311 DEBUGA = 00 X = 00 Y = 00 P = 32 S = 00
Step 8As above.G 3312 3314 DEBUGA = FF X = 00 Y = 00 P = B0 S = 00
Step 9As above.G 3315 3317 DEBUGA = 00 X = 00 Y = 00 P = 33 S = 00
Step AAs above.G 3318 331A DEBUGA = 02 X = 00 Y = 00 P = 30 S = 00
Step BAs above. This is the last step in our demonstration.G 331B 331D DEBUGA = 02 X = 00 Y = 00 P = 33 S = 00

Each monitor has its own syntax for this; yours is illustrated in the appropriate figure. Monitor commands are fussy about spaces, etc., so pay close attention to details at this point. Now go do Step 4, which will start execution of the machine language routine at address $3300. That routine will run until a BRK instruction is executed, at which point processing will stop and the monitor's register display will appear on the screen. When that happens, which should be immediately, come back here.

Step 4. Study the register display, disregarding IRQ and SP, and observe that AC, XR, and YR are all set to $00. (Non-Commodore people observe the same thing, labeled A, X, and Y.) Use the table to confirm that $30 means that all SR (or P) flags are clear, except for the B and the meaningless bit that's always set. Remember what the B flag is for, and it will be easy to see why it's set. Our program was designed to zero everything out, and it worked as it was designed. So far, so good. (If things are not so good, you've made a mistake. Repeat your work from the beginning.)

Nothing Has Changed

Step 5. Now perform Step 5, and notice what has happened. The program has loaded $80 (1000 0000) into the accumulator, and the monitor AC display so indicates. Since the high-order bit of $80 is a 1, the computer set its own N flag. The program counter has advanced, but nothing else has changed. (If your stack pointer changed, never mind—the monitor, not our program, changed it.) The BRK brought us back to the monitor. Simple, isn't it?

Step 6. The LDA has loaded $7F (0111 1111) into the accumulator, setting N to match its highest bit. The register display shows the $7F, and proves that N is now clear, while all other flags remain the same. Now do Step 7.

Step 7. Putting $00 (0000 0000) in the accumulator sets the Z bit, since zeros beget zeros. Notice how the PC is stepping right along with us, and do Step 8.

Step 8. $FF (1111 1111) is not a zero, so the zero flag is cleared. Its high bit is a 1, so the N flag is set. Move on to the next step.

Step 9. The ADC instruction adds 1 to the accumulator. Like driving another mile when the speedometer reads 99999, this rolls the accumulator over to $00 (0000 0000). We can tell when this happens, because the rollover automatically sets the carry flag. The carry bit is often used in just this way, to tell when a counter has reached its maximum. In our example, Z is also set, since the operation resulted in a zero. When you've absorbed those simple details, go on to Step A.

Bump A Counter

Step A. The last operation did not roll over the accumulator, so the carry bit was cleared. What it did was to add 1 to the zero in the accumulator, giving a result of 2. How on earth does 1 + 0 = 2? The answer is in the carry bit. An ADC adds its operand plus the carry bit to the contents of the accumulator, then reconditions C based on the result. That's very useful, because often when a counter rolls over, we want to increment a higher-order counter, so nothing gets lost in the counting. Many programs look for the carry bit, and bump a counter if it's set. Our own little program didn't go that far, but it did show us how such things can be done. Now do the next G.

Step B. What's this? We compared a 2 to a 2, and the zero and carry flags got set. That's a special use of flags in comparing numbers. CMP and the other comparison instructions don't store their results anywhere, but they do condition the N, Z, and C flags in a special way that facilitates branching after the comparison. Read up on the CMP, CPX, and CPY instructions for full information on how they set the flags.

Figure 3: Commodore Screen Dialogue

Step1To activate the monitor, type SYS 4, then press RETURN. (If you have a PET with original ROM, you must first load the monitor program from tape.)SYS4
B *
PC IRQ SR AD XR YR SP
. :0005 E62E 30 00 5E 04 F8
Step2Type this command, then press RETURN..M3300 331F
Step3You will see a display like this, but with different two-digit numbers. Carefully change them to these numbers by typing over them. Press RETURN at the end of each line.. :3300 D8 18 A9 00 AA A8 C9 FF
. :3308 00 A9 80 00 A9 7F 00 A9
. :3310 00 00 A9 FF 00 69 01 00
. :3318 69 01 00 C9 02 00 00 00
Step4Type the G 3300 command, then press RETURN. When this line appears, return to the text.. G3300
B *
PC IRQ SR AC XR YR SP
. :3309 E62E 30 00 00 00 F8
Step5This and the following steps are identical to Step 4, except for the numbers entered and displayed.. G3309
B *
PC IRQ SR AC XR YR SP
. :330C E62E B0 B0 00 00 F8
Step6As above.. G330C
B *
PC IRQ SR AC XR YR SP
. ;330F E62E 30 7F 00 00 F6
Step7As above.. G330F
B *
PC IRQ SR AC XR YR SP
. :3312 E62E 32 00 00 00 F6
Step8As above.. G3312
B *
PC IRQ SR AC XR YR SP
. :3315 E62E B0 FF 00 00 F6
Step9As above.. G3315
B *
PC IRQ SR AC XR YR SP
. :3318 E62E 33 00 00 00 F6
Step AAs above.As above.. G3318
B *
PC IRQ SR AC XR YR SP
. :331E E62E 30 02 00 00 F4
StepBAs above, but when the registers display appears, type X and press RETURN. Then go back to the text.. G331B
B *
PC IRQ SR AC XR YR SP
. :331E E62E 33 02 00 00 F4

We're now at the end of our flag-waving tour. If you kept with us this far, you're in the know about some elementary but important attributes of the processor status register, and you may have improved your knowledge of your monitor. Dig into those ML texts that you didn't understand last time, and you'll be surprised how easy they've become. If you're really feeling like an expert, come up with a branch instruction to take our program back to $3300.

Machine Language Demonstration Program

3300 D8	CLD
3301 18	CLC
3302 A9 00	LDA #$00
3304 AA	TAX
3305 A8	TAY
3306 C9 FF	CMP #$FF
3308 00	BRK
3309 A9 80	LDA #$80
330B 00	BRK
330C A9 7F	LDA #$7F
330E 00	BRK
330F A9 00	LDA #$00
3311 00	BRK
3312 A9 FF	LDA #$FF
3314 00	BRK
3315 69 01	ADC #$01
3317 00	BRK
3318 69 01	ADC #$01
331A 00	BRK
331B C9 02	CMP #$02
331D 00 BRK

Decoding status Displays

First DigitSecond Digit
00 DIZC
11 DIZC
2 NV - B2 DIZC
3 NV - B3 DIZC
44 DIZC
55 DIZC
6 NV - B6 DIZC
7 NV - B7 DIZC
88 DIZC
99 DIZC
A NV - BA DIZC
B NV - BB DIZC
CC DIZC
DD DIZC
E NV - BE DIZC
F NV - BF DIZC

This table decodes two-digit hex displays of the processor status register. Bold face indicates bit set; regular face, bit clear.