This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Confusion about BIT opcode

Confusion about BIT opcode
by on (#225527)
Hi Everyone,

I'm going through Brad Smith's (rainwarrior) ca65 example, and I'm confused about how the BIT opcode works.

Inside of his reset, he's doing a bit operation on the PPU STATUS ($2002) register and I'm trying to figure out why bpl (Branch on Plus) is used to branch back around waiting for the first V-Blank.

bit $2002
:
bit $2002
bpl :-

Earlier he loads #$40 into the Accumulator using an LDA
lda #$40

Is BIT comparing the A register to what's in $2002? If that's the case, isn't $40 = %0100 0000? According to the Yoshi document, the status register looks like this:
| $2002 | R | vhs00000 | PPU Status Register [PPUSTAT] |

where the vblank status is v, meaning in the left most bit. So I'm really confused as to how this part of the code works.

I would really appreciate it if someone could let me know why I'm failing so miserably to understand what is going on here.

Thanks for your help,
Rick
Re: Confusion about BIT opcode
by on (#225528)
BIT sets the negative flag based on the leftmost bit of the value read. The value of the A register is irrelevant here, and only affects the zero flag.
Re: Confusion about BIT opcode
by on (#225529)
BIT is only an AND result for the zero flag (BEQ/BNE).

The sign flag (BPL/BMI) after BIT is just the high bit of the value directly read from the operand. The value in A doesn't affect this result.

The overflow flag (BVS/BVC) is similar but with the second highest bit.

Reference here: http://www.obelisk.me.uk/6502/reference.html#BIT


Because of this ability of BIT to read the two high bits of a value directly, it's sort of standard design for 6502 status registers like this to put the important stuff in the top two bits.
Re: Confusion about BIT opcode
by on (#225530)
Others have answered already, but from a "programmer standpoint" or "operational standpoint", the reason the bit method is sometimes chosen is because it only affects CPU flags and leaves accumulator/X/Y alone (in contrast to, say, if you were to use lda/ldx/ldy). So bit $addr on the 6502 does nothing other than affect CPU flags in the following way (quoting book here, with some modifications of my own):

Code:
BIT is usually used immediately preceding a conditional branch instruction: to test a memory value’s
highest or next-to-highest bits; or with a mask in the accumulator, to test any bits of the memory operand.
All of these tests are non-destructive of the data in the accumulator or in memory.

CPU flags affected: n v - - - - z -

n = Takes value of most significant bit (bit 7) of memory data.
v = Takes value of next-to-highest bit (bit 6) of memory data.
z = Set if logical AND of memory and accumulator is zero; else cleared.
Re: Confusion about BIT opcode
by on (#225533)
Ok, I'm still a little confused, but here is what I think Brad is doing... please feel free to correct me if I'm wrong.

1.) Use BIT to copy the value of the 7th bit into the N flag in the status register
2. ) Use BPL (Branch on Plus) to continue looping as long as that flag is set to 0.

Since the 7th bit in the PPU Status register ($2002) is set to 1 if we are currently in a vblank the N (negative) bit in the status register would be set to 0 when we are NOT in a vblank. If we BPL (Branch on Plus) we are waiting as long as that bit continues to be 0 and stop looping as soon as the N bit is set to 1.

Sorry for all the confusion... the BPL was really throwing me off for a while. I'm hoping I understand what is going on now

Thanks,
Rick
Re: Confusion about BIT opcode
by on (#225536)
LDA would work equally well in this particular situation. Only disadvantage of LDA is overwriting the value in A, but that's only important if you need to reuse the value that was already there.

BIT is a bit of a weird instruction, but it's well suited to a polling loop like this, and it's kind of the "conventional" thing to do when polling $2002. For testing bit 7 or 6, there's might be no advantage over LDA, but if you ever need to poll multiple bits, or a bit in the middle of a register, BIT becomes the best way to do it.

For example, if you wanted to play a DPCM sound, and then wait for it to finish, we could poll bit 4 of the APU status register $4015:
Code:
; bit 4 of $4015 is DPCM sample status
lda #%00010000
:
bit $4015 ; zero flag is result of $4015 AND %00010000
bne :-

; without BIT your loop gets longer, which reduces the accuracy of your timing:
:
lda $4015
and #%00010000
bne :-
Re: Confusion about BIT opcode
by on (#225537)
battagline wrote:
Ok, I'm still a little confused, but here is what I think Brad is doing... please feel free to correct me if I'm wrong.

1.) Use BIT to copy the value of the 7th bit into the N flag in the status register
2. ) Use BPL (Branch on Plus) to continue looping as long as that flag is set to 0.

Since the 7th bit in the PPU Status register ($2002) is set to 1 if we are currently in a vblank the N (negative) bit in the status register would be set to 0 when we are NOT in a vblank. If we BPL (Branch on Plus) we are waiting as long as that bit continues to be 0 and stop looping as soon as the N bit is set to 1.

Correct.

If you want to know what this is for (and why), there's a wiki page that talks about it and even gives the code in question (see Best Practice -- read the section, don't skim it, and don't miss the race condition link either): https://wiki.nesdev.com/w/index.php/PPU_power_up_state
Re: Confusion about BIT opcode
by on (#225539)
rainwarrior wrote:
For testing bit 7 or 6, there's might be no advantage over LDA

LDA doesn't copy bit 6 to the V flag though, so that's one advantage of BIT. BIT makes it really convenient to use bits 7 and 6 for flags.
Re: Confusion about BIT opcode
by on (#225541)
Ah, yes, that slipped my mind. Corrected.

Anyway, if you forget about BIT except as an instruction that polls $2002 you'd probably be able to go a long way in NES programming without ever really needing it for anything else.
Re: Confusion about BIT opcode
by on (#225546)
I never really used it until recently ^^;;; I think I saw in one of rainwarrior sample for palette and wondered why then started used it in my code for polling $2002 for resetting the latch since I didn't have to overwrite a/x/y that way. I need to learn to use it though.

Now by reading the bit 6/7 and mask, I may find some use someday.
Re: Confusion about BIT opcode
by on (#225548)
rainwarrior wrote:
Ah, yes, that slipped my mind. Corrected.

Anyway, if you forget about BIT except as an instruction that polls $2002 you'd probably be able to go a long way in NES programming without ever really needing it for anything else.



Thanks again for your help. I'm just trying to understand what is going on, so I was running through the Yoshi doc and comparing it to what you were doing in your ca65 framework. I ran into that part and just didn't understand what was going on, so I figured everyone on this forum has been super helpful, so why not ask and learn? :-)
Re: Confusion about BIT opcode
by on (#225550)
"Yoshi doc" meaning Nestech.txt, right?
Re: Confusion about BIT opcode
by on (#225555)
@tepples,

Is the version you updated and that is now available in the wiki still available in plain text format? Wiki is nice, just like the older format too ^^;;
Re: Confusion about BIT opcode
by on (#225556)
Banshaku wrote:
Is the version you updated and that is now available in the wiki still available in plain text format? Wiki is nice, just like the older format too ^^;;

The wiki has a printable version link in the sidebar. In firefox you can then save that webpage as plain text, and it does an OK job converting the markup into readable txt.
Re: Confusion about BIT opcode
by on (#225557)
Banshaku wrote:
I think I saw in one of rainwarrior sample for palette and wondered why...

For that particular application, BIT $2007 is a convenient way to increment the PPU address without affecting A/X/Y.
Re: Confusion about BIT opcode
by on (#225566)
Yes, that's one way to get it back in text, didn't think about that. I will check how close it is from original then. thanks.

As for BIT, I wouldn't have thought to use it that way (well, I never really used bit so.. ^^;;). The more I see those usage pattern, the better I will use them. For now I'm not using it but it could be useful in some situation when you need to skip some specific data. I have some ideas coming already when modifying bg attributes or other cases like that.