Question on conditional branch

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Meterman58761
Posts: 19
Joined: 05 Jun 2021

Question on conditional branch

Post by Meterman58761 »

So, I've got the bit of code I've been working on mostly cleaned up and reorganized to flow more efficiently and logically, but there's still one bit that has me scratching my head.

Perhaps it's a bit of leftover cruft that was never tidied up (wouldn't be surprised, given the inefficient use of code and inconsistencies I'd found along the way).

Here goes:

Code: Select all

LB_E12B	JSR	LB_FA63
		LDA	$B9
		ASL
		BCC	LB_E15E
		LDY	$BD
		CPY	#$0B
		BNE	LB_E15E
		LDX	#$00
		STX	$0C69
		AND	#$06		???
		BEQ	LB_E159		???
                LDX #$F0
                STX $0C6B
                LDX #$FF
		STX	$0C6C
		CMP	#$02		???
		BEQ	LB_E159		???
		LDX	#$00
		STX	$0C6B
		STX	$0C6D
		STX	$0C6F
LB_E159	JSR	LB_F0F6
		JMP	LB_E12B
LB_E15E   ASL
               BCC ...
The ONLY values that are stored in $B9 are: 00, 14, 4C, A4, AD, or AE.

I can't see how any of these values, if shifted left, would meet either conditional, or am I missing something?
Last edited by Meterman58761 on Thu Oct 14, 2021 10:57 pm, edited 1 time in total.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Question on conditional branch

Post by barrym95838 »

There's something fishy about that code, especially the LDX #$F0FF, which suggests to me that your disassembler is getting out of sync. That's not the only instruction, but it sticks out like a sore thumb to me. Can you share the hex? It's possible that we can see why your disassembler apparently got confused.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: Question on conditional branch

Post by BillG »

BillG wrote:

Code: Select all

00 14 4C A4 AD AE   Your numbers
00 28 98 48 5A 5C   shifted left
00 00 00 00 02 04   and anded with 6
AD and AE will fall through the first BEQ

AE will fall through the second.
Meterman58761
Posts: 19
Joined: 05 Jun 2021

Re: Question on conditional branch

Post by Meterman58761 »

Barry: I grabbed the wrong bit of code before posting (it was a too-quick copy / clean / paste from the original 68xx code). I made a correction that should help.
Meterman58761
Posts: 19
Joined: 05 Jun 2021

Re: Question on conditional branch

Post by Meterman58761 »

I guess I'm a bit confused on the proper use of AND in conjunction with BEQ / BNE versus in conjunction with CMP.

So, if I do the AND with 6, leaving 0, then the Z flag goes up, at which point BEQ kicks in, right?

Whereas my thinking of BEQ has centered on whether the remainder after being ANDed is equal to 6 or not...
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Question on conditional branch

Post by GARTHWILSON »

Meterman58761 wrote:
I guess I'm a bit confused on the proper use of AND in conjunction with BEQ / BNE versus in conjunction with CMP.
CMP does a subtraction, without regard to the carry flag, nor keeping the result. It also does not set the V flag; so it cannot be used for signed comparisons. All it does is modify the N, Z, and C flags. If the result of the subtraction is 0, the Z flag gets set.

Quote:
So, if I do the AND with 6, leaving 0, then the Z flag goes up, at which point BEQ kicks in, right?

AND is a bitwise AND. AND #6, ie, AND %00000110, zeroes six of the eight bits, every accumulator bit except bits 1 and 2, and sets the Z flag if both those remaining bits are 0; otherwise it clears it. It also also transfers the msb to the N flag; and in this case, since you ANDed with a number that has 0 in the msb, N will be cleared, regardless of what number you started with.

Quote:
Whereas my thinking of BEQ has centered on whether the remainder after being ANDed is equal to 6 or not...

No; 6, bitwise-ANDed with 6, still results in 6, ie 00000110 in binary, which is definitely not zero, so the Z flag will not be set.

I strongly recommend you get the "Programming the 65816—Including the 6502, 65C02 and 65802" 6502/65816 programmer's manual by David Eyes and Ron Lichty. This is definitely the best 65xx programming manual available, and a must-have for every 65xx programmer! It starts with the basics, followed by architecture, the CMOS 65c02's many improvements over the original NMOS 6502 including added instructions and addressing modes and fixing the NMOS's bugs and quirks, and then the natural progression to the 65816; a thorough tutorial, writing applications, then very detailed and diagrammed information on all 34 addressing modes, at least a page of very detailed description for each instruction, with info on every addressing mode available for that instruction, then instruction lists, tables, and groups, of all 255 active op codes, plus more. 469 pages. From Western Design Center. (.pdf) Note: There were many problems with the earlier .pdf version that were not in the original paper manual; but in late March 2015, WDC scanned and OCR'ed the paper manual and posted the new, repaired .pdf.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Question on conditional branch

Post by BigEd »

From this angle it does look a little as if BEQ could have been named BZS: it's a test of the Z flag. We can think of BEQ as testing for zero - but we do need to know that CMP does a silent subtraction. It's a great instruction set, but I see now how it has some nooks and crannies, and takes a little getting used to.

It's very valuable to have explanations from someone who is learning the ropes. It can be difficult to see something with fresh eyes when you're very familiar with it.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Question on conditional branch

Post by GARTHWILSON »

BigEd wrote:
From this angle it does look a little as if BEQ could have been named BZS: it's a test of the Z flag. We can think of BEQ as testing for zero - but we do need to know that CMP does a silent subtraction.
Some (many?) assemblers allow you to define aliases for the standard mnemonics.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Meterman58761
Posts: 19
Joined: 05 Jun 2021

Re: Question on conditional branch

Post by Meterman58761 »

There we go. Looks like that was the last bit that needed cleaning.

Now that I got the last of the spaghetti picked out and the one 'test byte' ($B9) documented in regards to which conditionals are tripped by which values, I can focus on the interrupt section.

I guess from seeing CMP and BEQ / BNE paired many times through the years, I had a flawed understanding of exactly what those specific opcodes do.

I never really realized that CMP does a silent subtraction (just like BIT's 'silent' AND), but that now explains why I see a few CMP and BPL / BMI pairs in the code.

I guess that one could theoretically set up CMP to work with BCC / BCS or even BVC / BVS, right? (although I don't see where I would need to).

I think BZS would be too easy to confuse with BCS or BVS. Perhaps it should be BEZ / BNZ. Ah well! I (re)learned something, and that's what counts!
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Question on conditional branch

Post by GARTHWILSON »

Meterman58761 wrote:
I guess that one could theoretically set up CMP to work with BCC / BCS or even BVC / BVS, right? (although I don't see where I would need to).
Again, CMP does not affect the V flag.
Quote:
I think BZS would be too easy to confuse with BCS or BVS. Perhaps it should be BEZ / BNZ. Ah well! I (re)learned something, and that's what counts!
BZS (Branch if Zero flag Set) should not be confusable with anything regarding the Carry or oVerflow flags. The flags are separate for a reason.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Question on conditional branch

Post by GARTHWILSON »

Perhaps I should have added a part from the "Programming tips" page of the 6502 primer at http://wilsonminesco.com/6502primer/PgmTips.html, from just after the heading "Avoid commonly wasted instructions:" almost halfway down the page:

  • 1. An automatic compare-to-zero instruction is built into the following 65c02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX. This means that, for example, a CMP #0 after an LDA is redundant, a wasted instruction. A kitten somewhere dies every time you do that! :lol: The only time a 65c02 (CMOS) needs a compare-to-zero instruction after one of these is if you want to compare a register that was not involved in the previous instruction; for example,

    Code: Select all

            DEY
            CPX  #0
    (Note the Y and the X are not the same register.) If you can spare a register to which you can transfer the one you want to test, you can save a byte with the transfer instead of a compare instruction. The example above, if the contents of A don't need to be kept, could be changed to:

    Code: Select all

            DEY
            TXA
    and then you can branch on the N or Z flag which tell if X was negative or zero. The TXA isn't any faster (both TXA and CPX# take two clocks); but TXA takes only one byte, whereas the CPX #0 takes two bytes.

    The NMOS 6502 did have a bug in that the flags weren't always correct after a decimal-mode operation like ADC; so then you might have to follow it with the CMP #0 to get the N and Z flags right. It's best to just use the CMOS processor for any new projects.

    2. Similarly, if you want a compare to $80 strictly for branching on the N flag results, you can omit the compare-to-$80 instruction and branch on the opposite state of the N flag. For example

    Code: Select all

            DEA            ; (same thing as DEC A)
            CMP  #$80
            BMI  <label>
    can be replaced with

    Code: Select all

            DEA            ; (same thing as DEC A)
            BPL  <label>
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Question on conditional branch

Post by BigDumbDinosaur »

BigEd wrote:
From this angle it does look a little as if BEQ could have been named BZS...

There are historical reasons why BEQ is BEQ and not something else—also true for the other branching instructions.

Recall that the 6502's grandfather is the MC6800. MOS Technology believed that adopting most of the 6800 assembly language would encourage engineers to adopt the 6502, since it would be relatively easy to port 6800 programs. Since the 6800 used BEQ, BNE, etc., for branching mnemonics, the 6502 inherited those instructions, along many others. Of course, there were quite a few 6800 instructions that were deleted for cost-reduction reasons (RIP BSR)...only for a few to reappear in the 65C02 and 65C816.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Question on conditional branch

Post by BigDumbDinosaur »

Meterman58761 wrote:
I never really realized that CMP does a silent subtraction (just like BIT's 'silent' AND)...

As Garth mentioned above, all of this is described in great detail in the Lichty & Eyes manual, which we highly recommend you read. The 6502 family is probably the most documented microprocessor family of all time, so there really isn't any excuse for not having plenty of reference materials on hand as you learn the assembly language.

Quote:
but that now explains why I see a few CMP and BPL / BMI pairs in the code.

CMP followed by BPL or BMI can get the unwary beginning programmer into trouble. BPL and BMI test the state of the N flag in the status register (SR). As Garth noted, comparison is a subtraction that discards the difference and only affects SR, specifically the C, N and Z flags. The effect on N is the result of signed subtraction, which won't always result in what you might expect.

For example, the following code doesn't work the way you'd think it would:

Code: Select all

         lda #$00
         cmp #$FF
         bmi less_than

The branch to LESS_THAN will not be taken, even though $00 appears to be "lower" than $FF.

Quote:
I guess that one could theoretically set up CMP to work with BCC / BCS or even BVC / BVS, right? (although I don't see where I would need to).

Again, you need to do some reading. CMP doesn't "work" with the branch instructions. What CMP does is condition SR flags. In some cases, CMP may not be followed by a branch, as it is the effect on the flags that was what prompted the use of CMP. For example, an addition, subtraction or some other operation that is not a branch may follow CMP, taking advantage of how CMP affected carry.

As for use of BCC and BCS, those are frequently employed to determine if a compared value is the same as, higher or lower than the comparison value, since there is no specific "greater than" or "lesser than" branch instruction. For example, here are two frequently-used comparison sequences involving both C and Z:

Code: Select all

         lda value1
         cmp value2
         bcc lower             ;value1 < value2
;
         bne higher            ;value1 > value2

or...

Code: Select all

         lda value1
         cmp value2
         bcs same_greater      ;value1 >= value2

Again, carry results from the subtraction of CMP.

CMP, also CPX and CPY, won't affect the V flag, so use of BVC or BVS following a comparison would be ambiguous at best. Those branches are primarily of value when carrying out signed arithmetic, or when using BIT to test flags, since BITing a memory location will copy bits 6 and 7 into V and N, respectively.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Question on conditional branch

Post by BigEd »

(Edit: see downthread. This tutorial may be mistaken about signed values.)

I recommend this document on branches, if you really want to understand deeply:
http://6502.org/tutorials/compare_instructions.html

It notes there that the C flag is useful when the inputs are considered unsigned values, and the N flag is useful when they are considered signed values.
Last edited by BigEd on Mon Oct 18, 2021 4:33 pm, edited 1 time in total.
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Question on conditional branch

Post by BigDumbDinosaur »

BigEd wrote:
I recommend this document on branches, if you really want to understand deeply:
http://6502.org/tutorials/compare_instructions.html

It notes there that the C flag is useful when the inputs are considered unsigned values, and the N flag is useful when they are considered signed values.

Yes, the tutorial does say that, and I'll return to that in a few sentences, but what I was pointing out was the use of BPL or BMI following a CMP can take a programmer down a dirt road. The implied subtraction carried out by CMP is always unsigned. My previous example of CoMParing $FF to $00 illustrates this.

Regarding the tutorial, its recommendation to use BPL and BMI in signed comparisons is incorrect. Rather than have anyone take my word for it, I'll quote something from the Eyes & Lichty manual:

  • There are also no branch instructions available for signed comparisons, other than equal and not equal.
(Page 151, emphasis added.)
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply