Page 1 of 1
Branching - how does it work?
Posted: Thu Aug 30, 2018 5:59 am
by Atlantis
I have to admit, I am a little bit confused. I always thought that situation is straightforward.
Let's assume we have a following situation.
Code: Select all
LDA variable
CMP #$10
BEQ LABEL
; these are instructions executed when variable != 16
; program simply continues to execute, increasing program counter
; you have to take care of it, to not hit LABEL after it's done
; for example by using RTS or JMP instruction
LABEL:
; this is set of instructions executed when variable == 16
; program jumps here after BEQ LABEL
But recently I was looking at a code compiled by CC65. There is a following fragment of a main() function.
Code: Select all
if (variable < 16) {
hd44780_putc('A');
}
while(1) { }
It is compiled as:
Code: Select all
lda _variable
cmp #$10
L001F: bcs L001F
lda #$41
jsr _hd44780_putc
L001E: jmp L001E
Can anyone explain me how does it works? It looks like bcs instruction points at itself, by using L001F label.
Can it be done that way? Will bcs simply jump to the next label (L001E in that case) if variable is less or equal than 0x10?
Re: Branching - how does it work?
Posted: Thu Aug 30, 2018 6:45 am
by hmn
Code: Select all
lda _variable
cmp #$10
L001F: bcs L001F
That is simply an endless loop if _variable >= 16. So that is equivalent to your C code. The compiler just decided to implement your endless loop twice.
Re: Branching - how does it work?
Posted: Thu Aug 30, 2018 4:36 pm
by JenniferDigital
No, you were on the right track the first time!
Firstly, the C code you wrote isn't functionally identical to the assembly code and secondly, CC65 doesn't produce very optimal code. CC65 still needs some of it's rough edges and documentation polishing and on my wishlist is support for floats and doubles (and I don't care what the whingers say about floats and doubles being slow on a 6502, they can go away).
BEQ branches when Z is set,
BCS branches when C is set.
you could have said "!=" in C instead.
Re: Branching - how does it work?
Posted: Fri Aug 31, 2018 4:46 pm
by whartung
Firstly, the C code you wrote isn't functionally identical to the assembly code and secondly, CC65 doesn't produce very optimal code.
It is a curious situation that the compiler implemented the endless loop twice, however.
Re: Branching - how does it work?
Posted: Fri Aug 31, 2018 11:00 pm
by barrym95838
Will bcs simply jump to the next label (L001E in that case) if variable is less or equal than 0x10?
I believe that "BCS" on the 65xx is equivalent to "BCC" or "BHS" from 680x/680x0-lands, which means branch if
unsigned >= (assuming the flags were preconditioned by a compare or subtract instruction).
Re: Branching - how does it work?
Posted: Sat Sep 01, 2018 7:48 pm
by BillO
While it would have been no more efficient, it would have read better and been less confusing if the compiler code read:
Code: Select all
lda _variable
cmp #$10
L001F: bcs L001E
lda #$41
jsr _hd44780_putc
L001E: jmp L001E
Re: Branching - how does it work?
Posted: Sat Sep 01, 2018 8:54 pm
by JimBoyd
Will bcs simply jump to the next label (L001E in that case) if variable is less or equal than 0x10?
I believe that "BCS" on the 65xx is equivalent to "BCC" or "BHS" from 680x/680x0-lands, which means branch if
unsigned >= (assuming the flags were preconditioned by a compare or subtract instruction).
BCS on the 6502 branches on carry set and BCC branches on carry clear. Subtraction
clears the carry if the subtraction results in a borrow and
sets it otherwise. Comparisons have the same effect on the carry flag as subtraction. In the following code snippet it may appear that nothing is subtraced from memory location
COUNTER but because the carry flag is cleared, one is subtracted from
COUNTER.
Code: Select all
define COUNTER_LO $0
define COUNTER_HI $1
LDA #$00
STA COUNTER_LO
LDA #$02
STA COUNTER_HI
CLC
LDA COUNTER_LO
SBC #$00
STA COUNTER_LO
LDA COUNTER_HI
SBC #$00
STA COUNTER_HI
BRK
This example runs on easy 6502
http://skilldrick.github.io/easy6502/ as I think this will be easier to follow than my Forth assembler syntax.
Cheers,
Jim
Re: Branching - how does it work?
Posted: Sat Sep 01, 2018 9:48 pm
by JimBoyd
I forgot to mention when you try this code on easy 6502
http://skilldrick.github.io/easy6502/, after assembling the code, click the monitor button and the debugger button. Single step through the code to see the carry flag and memory locations change.
Re: Branching - how does it work?
Posted: Wed Sep 19, 2018 9:11 pm
by JimBoyd
I ran across this the other day. Just wish I found it sooner.
The SBC, TSX, and TXS Instructions of the 6502 and 6800
by B.T.G. Tan
Dr Dobbs Journal #79 May 1983 page 67
http://6502.org/documents/publications/ ... s_journal/
It's in Volume 8.
Re: Branching - how does it work?
Posted: Wed Sep 19, 2018 9:50 pm
by GARTHWILSON
page 280 of the .pdf file
Re: Branching - how does it work?
Posted: Thu Sep 20, 2018 7:07 am
by BigEd
BTW another way to read Mike's scans of DDJ is at the internet archive:
https://archive.org/details/dr_dobbs_journal
and then we can link directly to the article:
https://archive.org/stream/dr_dobbs_jou ... 9/mode/1up
Thanks for the tip!
Re: Branching - how does it work?
Posted: Tue Nov 27, 2018 7:51 pm
by ghedger42
Make _variable a volatile, to force the compiler to read it each time and prevent optimizing the infinite loop.
Re: Branching - how does it work?
Posted: Wed Nov 28, 2018 9:20 am
by BigEd
(Welcome to the forum ghedger42!)
Re: Branching - how does it work?
Posted: Mon Dec 03, 2018 9:06 pm
by Mike Naberezny
It's great to see the Dr. Dobb's scans are being put to good use.
This particular article is also available as a
separate PDF under
Dr. Dobb's Selected Articles (suggested by Ed).
Re: Branching - how does it work?
Posted: Mon Dec 03, 2018 9:58 pm
by White Flame
It seems quite an omission that it doesn't actually show you how to do stack-relative addressing on the 6502:
Of course, this doesn't support $01ff->0100 wrapping as PHA/PLA would, but that's usually a stack underflow anyway.