Jump to content



1

bne jmp bpl


34 replies to this topic

#1 Serguei2 OFFLINE  

Serguei2

    Moonsweeper

  • 284 posts
  • Location:Canada

Posted Tue Apr 13, 2004 5:12 PM

Are bne, jmp, bpl the same function? Or different?

I found them in the 2600 tutorials.


Serguei2

#2 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Tue Apr 13, 2004 5:19 PM

bne means Branch if Not Equal (to zero).

If a computation produces a result other than zero, then the Z flag is not set, and the bne instruction will cause a jump to a new location in the program (otherwise, the next instruction in the program is executed).

bpl means Branch if Plus.

Often programmers use the topmost bit as a negative sign bit.
If a computation produces a result where bit 7 is not set, then the N flag is also not set, and the bpl instruction will cause a jump to a new location in the program (otherwise, the next instruction in the program is executed).

jmp means Jump.

A jmp instruction is always taken.

-Bry

#3 Serguei2 OFFLINE  

Serguei2

    Moonsweeper

  • 284 posts
  • Location:Canada

Posted Tue Apr 13, 2004 5:31 PM

That's why I never see "if then else" in Andrew Davie's sessions or even
(if xxxxx == 33){

}




lda xxxxx
cmp #33
bne elsenot33 ; take branch only if xxxx is NOT = 33

; this stuff done when xxxx IS = 33
jmp finished ; now unconditionally jump past the 'else' code

elsenot33

; this stuff done when xxxxx not = 33

finished

; we've just done an 'if-then-else' in assembler

#4 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Tue Apr 13, 2004 5:50 PM

Assembly language has no features like if, else, etc... But they are easily constructed using branch instructions.

It sounds like you need a good 6502 tutorial. Try looking here:

http://www.6502.org

http://www.geocities...ns/65index.html

-Bry

#5 Serguei2 OFFLINE  

Serguei2

    Moonsweeper

  • 284 posts
  • Location:Canada

Posted Tue Apr 13, 2004 5:57 PM

bryede said:

It sounds like you need a good 6502 tutorial. Try looking here:

http://www.6502.org

http://www.geocities...ns/65index.html

   -Bry

You're right. I never touched the machine languages until I followed
Andrew Davie's tutorials.

Thanks for the tips and the links.


Serguei2

#6 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Tue Apr 13, 2004 6:00 PM

It's not hard, you just have to "forget" a lot of what you know from high-level languages. :) The way I learned was to walk through simple routines until I figured them out.

-Bry

#7 Dan Iacovelli OFFLINE  

Dan Iacovelli

    River Patroller

  • 4,350 posts
  • Location:westchester,IL

Posted Tue Apr 13, 2004 6:07 PM

some of the instructions are close to basic code:

JMP is like Goto commnad in basic
JSR is like to Gosub command in basic
RTS is like Return commnad in basic.

Iasked this question in my early years in stella list.

#8 Serguei2 OFFLINE  

Serguei2

    Moonsweeper

  • 284 posts
  • Location:Canada

Posted Tue Apr 13, 2004 7:02 PM

Thanks everybody


I also downloaded the Stella programmer's guide. It might help me to make my own 2600 games.


Serguei2

#9 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Tue Apr 13, 2004 11:33 PM

Substituting branching instructions for jumps is also a good way of reducing the number of bytes or cycles in a routine when hacking games (you need to watch your cycle times when the display is being constructed tho). Branches use 1 less byte and 1 less cycle than a JMP. The downside is that they can only direct a program to go 128 bytes forward or back. Branch descriptions:

BCC - branch on carry clear. This is most commonly used to check values that are less than what you are comparing it to...
LDA $DF ;get value of a ram location
CMP #$0A ;check if it's a value of 10
BCC $50 ;if $DF is less than that, take the branch

You can also use it to check for rollovers during arithmatic. You should use CLC or SEC instructions just prior to using ADC or SBC (respecively) if there is a possibility of the byte rolling over $FF or under $00. The status of that carry can also be used in adding or subtracting values that are larger than $FF...
LDA $A8 ;load the low byte of our "score"
CLC ;clear the carry flag
ADC #$01 ;add 1 point **
STA $A8 ;...and save it
LDA $A9 ;load the high byte of our "score"
ADC #$00 ;if the carry flag was set by **, it will be adding 1 here
STA $A9 ;...and then save it

BCS - branch on carry set. This is the opposite from above, the branch is taken if the result is greater than the value you are checking for.

BEQ - branch on zero. This one checks if they are equal. If our example $DF is equal to $0A...there will be no remainder when comparing it against a value of $0A - branch on zero. You can also use it just to see if the contents of a memory location are equal to zero...
LDA $DF ;load the ram location
BEQ $50 ;if it's zero, take the branch

BNE - branch if not zero. The opposite from the above...the program will take the branch if the result is anything BUT zero (i.e. not equal to).

BMI - branch on minus. The branch is taken if the high bit is set ($80 to $FF are considered to be negative)

BPL - branch on plus. The opposite from the above, the branch is taken if the result is between $00 and $7F. Really handy to use in loops that count down. You'll see it used often in display kernals where a specific amount of time needs to be wasted...
LDX #$10 ;start with a value of 16 decimal
DEX ;subtract 1 (doing nothing for 2 cycles)
BPL $FD ;also using 2 cycles, branch back up until X rolls over to $FF.

BVC - branch on overflow clear. This is similar to BPL...you are just looking at one bit in the value to see if it's not set (the second-highest bit...which has a value of $40)

BVS - chanch on overflow set. The opposite from the above. The branch will be taken if that bit is on. Since the 2600 is seriously limited for ram space, variables are often shared in a single ram location. No need to waste a full byte if all you want to do is toggle something on or off :) The code...
LDA $F0 ;load a ram location
AND #$40 ;keep only the second-highest bit
BEQ $E0 ;branch if that bit is off

...can be shortened to...
LDA $F0 ;load a ram location
BVC $E0 ;branch if bit 6 is off

...and if you don't want your accumulator's value to be overwritten, you could even do this...
BIT $F0 ;check a ram location
BVC $E0 ;branch if bit 6 is off

...but I won't go into that :D


That covers branches...but JMP also has a couple of formats. You probably already know JMP $location...always jump to the address unconditionally, but there is another one that is used when you want to have a choice of jumping to one of many locations from within the program. It's indirect jumping...that is to say that the program looks up 2 ram locations and jumps to the address that THEY contain. Although all of the 2600's ram is located only on single-byte zero page locations, the instruction still uses 3...so the high byte is usually zero...
Example:
JMP ($00D0)
This instruction is looking at the contents of $D0 and $D1 for the address to jump to. If $D0=$05 and $D1=$F1, the jump will go to $F105. Often, these values are located in a table located someplace in Rom...and the program puts the one it needs (depending on what is currently happening) into the ram locations just prior to using the indirect JMP.

And as stated above, JSR acts as Basic's GOSUB. It jumps to a new location, and saves the return address for when an RTS instruction is met. You still need to watch out for how many "nests" you can perform at one time tho. So the program might overwrite some of the ram locations used for variables if you use too many JSR's at the same time. JSR's are also the biggest wasters of cycle time...6 cycles to jump there and 6 cycles to return - that's 12 cycles and you didn't even do anything there!

#10 Andrew Davie OFFLINE  

Andrew Davie

    Stargunner

  • 1,314 posts
  • Location:Tasmania

Posted Tue Apr 13, 2004 11:44 PM

Nukey Shay said:

Substituting branching instructions for jumps is also a good way of reducing the number of bytes or cycles in a routine when hacking games (you need to watch your cycle times when the display is being constructed tho).  Branches use 1 less byte and 1 less cycle than a JMP.  The downside is that they can only direct a program to go 128 bytes forward or back.  Branch descriptions:


Thanks for that. I think we'll probably have to have a tutorial on branching. The above seems mostly OK, but there are a few more tricks/gotchas. For example, BCC is a branch less than only if the numbers you are dealing with are considered unsigned. For signed comparisons, BPL and BMI are used instead of BCC and BCS. To be honest, I almost never do signed comparisons... but something to be aware of.

On a slightly different subject, I'm playing around with a '2600 programming Wiki. See http://twiki.org/cgi...ox/AtariVCS2600 for an idea of what it might be like. Feel free, of course, to make changes -- that's what a wiki is all about. Takes a while to get used to, but looks VERY useful and powerful once you do. Highly recommended.

#11 Artlover OFFLINE  

Artlover

    Super Amazing Guy

  • 6,354 posts
  • Bad ass mother 3000, twice as fast as your ass.
  • Location:Miami, FL

Posted Wed Apr 14, 2004 1:45 AM

Assembly can be fun.

As was already said: Forget what you know about high-level languages.

True, true.

Once you do, and start thinking in Hex & Binary, it makes a lot of sense and is quite easy to work with.

Heck, I've never even used a real assembler. I used my C-128's built-in ML monitor to do all my programming. And it was still fun & easy. :)

Not to mention FAST. I needed to swap out a specific byte-pair in a graphic image. I wrote a program in Assembly & Basic 7 to do it. The basic program was 2k, took 23 minutes. The assembly program was like 300 something bytes and took 1.5 seconds. 8)

#12 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Wed Apr 14, 2004 5:26 AM

I forgot to mention that the BIT instruction can be used to perform very small "jumps" forward...skipping only 1 or 2 bytes. If you have a routine that looks like this:
LDA $80,X ;check our group of ram values
CMP #$30 ;compare to a value of $30
BCC Load2 ;if it's lower, branch ahead
LDA #0 ;...otherwise load a zero
BEQ Save ;...and skip ahead to save it
Load2: LDA #$20 ;use $20 for the ones that were lower than $30
Save: STA $90,Y ;save it to the other group of ram values

...you have all 3 registers in use. X is being used for the offset in the first table, Y is being used as the offset in the second table, and the accumulator is occupied holding the value we want to save. Since all BEQ Save is doing is skipping ahead 2 bytes, we can use BIT $absolute instead...
LDA $80,X ;check our group of ram values
CMP #$30 ;compare to a value of $30
BCC Load2 ;if it's lower, branch ahead
LDA #0 ;...otherwise load a zero
.byte $2C ;...and skip ahead to save it
Load2: LDA #$20 ;use $20 for the ones that were lower than $30
Save: STA $90,Y ;save it to the other group of ram values

$2C is the value of the BIT $absolute instruction. So the computer will read this as the following when it's loading the zero...
LDA #0
BIT $20A9
STA $90,Y

Where did that $20A9 come from? The BIT instruction read the next instruction (LDA #$20) as a two-byte address...and is "fooled" into jumping two bytes ahead. So what is at $20A9? Who cares...the important thing is that we skipped over it. That replaced the BEQ instruction (2 bytes) with just 1. BIT $zeropage can be used to skip just 1-byte instructions ahead...one like an INX instruction.

#13 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Wed Apr 14, 2004 9:41 AM

Umm.. Serguei2 is still at the "learning to branch" stage. It might be best if he avoids the rest of this topic for a while. :)

-Bry

#14 kisrael OFFLINE  

kisrael

    HMBL 2600 coder

  • 3,970 posts
  • Location:Boston Burbs, MA

Posted Wed Apr 14, 2004 10:48 AM

Serguei2 said:

Thanks everybody
I also downloaded the Stella programmer's guide. It might help me to make my own 2600 games.
Have you written much in other languages? If you're not used to programming in general the atari is a very tough place to start.

You also might want to read through my own 2600 101, a kind of quickstart guide to programming the atari. It's built up around building a basic working program as quickly as possible, and then learning how to do more and more. (Also, my upcoming 2600 Cookbook, might already be useful on the few additional topics it covers)

#15 Serguei2 OFFLINE  

Serguei2

    Moonsweeper

  • 284 posts
  • Location:Canada

Posted Wed Apr 14, 2004 12:06 PM

kisrael said:

Have you written much in other languages?  If you're not used to programming in general the atari is a very tough place to start.

I know Basic, Qbasic, Klik & Play, AGI and SCI0.

Somebody told me programming c64 (assembler) is easier than 2600 but
I didn't check it at the moment.

I just finished my 3 playfields for my 3 levels at the moment. Now I have to deal with sprites by following the tutorials.


Serguei2

Attached Thumbnails

  • test.gif


#16 ErikM OFFLINE  

ErikM

    Space Invader

  • 21 posts
  • Location:New York

Posted Mon Apr 19, 2004 4:44 PM

Nukey Shay said:

LDA $F0 ;load a ram location
BVC $E0 ;branch if bit 6 is off

Actually, that doesn't work. LDA doesn't affect the overflow flag. I've gotten burned by that a couple times, in fact.

Quote

BIT $F0 ;check a ram location
BVC $E0 ;branch if bit 6 is off

This does work; BIT *does* set or clear the V flag as appropriate.

According to my 6502 reference, the *only* computational instructions that affect the V flag are ADC and BIT. (PLP and RTI also do, by pulling it from stack, and of course CLV clears it.)

Instructions that don't affect the overflow flag, but you might think they do, are LDA/LDX/LDY, CMP/CPX/CPY, SBC, all the IN_ and DE_ ops, and all the T__ transfer ops.


Here's how to remember how the sign and carry flags work with the compare instructions. CMP does the same thing as SEC+SBC without changing the accumulator. So suppose A holds the number 55, and we do CMP #30. The result of the 55 - 30 would be 25, binary %00011001. The topmost bit of the result is clear, so the sign flag is; and the result of the subtraction did not go below 0 so the carry stays set.

Suppose A held 30, and we did CMP #55. The result of the subtraction would be -25, or in binary %11100111. The topmost bit is set, so the sign bit is set (meaning negative). And the result of the subtraction went below 0, so the carry gets cleared.

CPX and CPY behave the same as CMP, of course.

Maybe Andrew can work that into a more coherent form for the tutorial lesson on branching. :)

#17 EricBall OFFLINE  

EricBall

    Dragonstomper

  • 711 posts
  • Location:Markham, Ontario, Canada

Posted Mon Apr 19, 2004 8:09 PM

ErikM said:

According to my 6502 reference, the *only* computational instructions that affect the V flag are ADC and BIT.  (PLP and RTI also do, by pulling it from stack, and of course CLV clears it.)

Instructions that don't affect the overflow flag, but you might think they do, are LDA/LDX/LDY, CMP/CPX/CPY, SBC, all the IN_ and DE_ ops, and all the T__ transfer ops.

Wrong, SBC does too. (See http://www.6502.org/...6502opcodes.htm for a good 6502 opcode list.)

ADC, BIT, CLV, PLP, RTI and SBC all update the oVerflow flag.
CLV clears it, BIT grabs bit 6 from the memory location, and PLP and RTI pull the entire Processor Status (aka Flags) Register from the stack.

See http://www.6502.org/...ials/vflag.html for more on the oVerflow flag.

On a related note, IN_ and DE_ also do not change the Carry bit.

#18 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Mon Apr 19, 2004 9:12 PM

Thx...I thought something was amiss

I've LDA/BVC'd plenty of times in _____ ;) Sadly, the 6502 won't allow BIT to use X or Y offsets :(

#19 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Mon Apr 19, 2004 9:54 PM

I don't think the compare instructions affect V.

-Bry

EricBall said:

Wrong  (See http://www.6502.org/...6502opcodes.htm for a good 6502 opcode list.)

ADC, BIT, CLV, CMP, CPX, CPY, PLP, RTI and SBC all update the oVerflow flag.
CLV clears it, BIT grabs bit 6 from the memory location, and PLP and RTI pull the entire Processor Status (aka Flags) Register from the stack.

See http://www.6502.org/...ials/vflag.html for more on the oVerflow flag.

On a related note, IN_ and DE_ also do not change the Carry bit.

Attached Thumbnails

  • syn_65_cmp.jpg


#20 ErikM OFFLINE  

ErikM

    Space Invader

  • 21 posts
  • Location:New York

Posted Mon Apr 19, 2004 11:04 PM

EricBall said:

Wrong  (See http://www.6502.org/...6502opcodes.htm for a good 6502 opcode list.)

ADC, BIT, CLV, CMP, CPX, CPY, PLP, RTI and SBC all update the oVerflow flag.
CLV clears it, BIT grabs bit 6 from the memory location, and PLP and RTI pull the entire Processor Status (aka Flags) Register from the stack.


Actually, the link that you give agrees with me that the compare instructions don't affect the V flag. "Affects Flags: S Z C".

And I listed all the other instructions you mention, except for SBC. Looks like my reference was wrong on that, but the point stands... the only opcodes that do something computational to the overflow flag are ADC, BIT, and SBC. CLV, PLP, and RTI do obvious things to it and are just about never used in 2600 programming anyway.


To Nukey Shay: LDA definitely doesn't update the overflow flag, so LDA/BVC definitely doesn't work. BIT/BVC certainly does, so that's probably what you've been using...?

#21 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Apr 20, 2004 2:51 AM

:idea: CMP, CPY, CPX do influence the V-flag.

http://www.chez.com/.....2 Opcodes.htm

#22 Cybergoth OFFLINE  

Cybergoth

    Quadrunner

  • 8,207 posts
  • This is Sparta!
  • Location:Bavaria

Posted Tue Apr 20, 2004 3:53 AM

Hi there!

Thomas Jentzsch said:

:idea: CMP, CPY, CPX do influence the V-flag.
http://www.chez.com/...502 Opcodes.htm

ErikM said:

Actually, the link that you give agrees with me that the compare instructions don't affect the V flag.

;)

Greetings,
Manuel

#23 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Apr 20, 2004 4:17 AM

Then just write a simple program and test it on real hardware (or trust the emulators).

#24 Cybergoth OFFLINE  

Cybergoth

    Quadrunner

  • 8,207 posts
  • This is Sparta!
  • Location:Bavaria

Posted Tue Apr 20, 2004 4:39 AM

Hi there!

Thomas Jentzsch said:

Then just write a simple program and test it on real hardware (or trust the emulators).

Ok, here's the code handling CMP in in Z26:
;*
;* flag setting macros
;*



useztest macro	op1	; use to test Z

	mov	[RZTest],op1

	endm



usentest macro	op1	; use to test N   

	mov	[RNTest],op1

	endm



usetest macro	op1	; use to test both N and Z (normal)

	useztest op1

	usentest op1

	endm


;*
;* compare macros
;*



CompDH macro  ; compare dh and dl

	sub	dh,dl

	usetest	dh

	setnc	ah

	endm



_CMP macro  ; compare al and dl

	mov	dh,al

	CompDH

	endm

usetest handles Z and N
setnc handles C.

No V code in sight :)

Greetings,
Manuel

#25 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Apr 20, 2004 4:56 AM

Ok, then someone should correct the wrong documentations.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users