Serguei2 Posted April 13, 2004 Share Posted April 13, 2004 Are bne, jmp, bpl the same function? Or different? I found them in the 2600 tutorials. Serguei2 Quote Link to comment Share on other sites More sharing options...
Bryan Posted April 13, 2004 Share Posted April 13, 2004 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 Quote Link to comment Share on other sites More sharing options...
Serguei2 Posted April 13, 2004 Author Share Posted April 13, 2004 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 Quote Link to comment Share on other sites More sharing options...
Bryan Posted April 13, 2004 Share Posted April 13, 2004 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.com/oneelkruns/65index.html -Bry Quote Link to comment Share on other sites More sharing options...
Serguei2 Posted April 13, 2004 Author Share Posted April 13, 2004 It sounds like you need a good 6502 tutorial. Try looking here: http://www.6502.org http://www.geocities.com/oneelkruns/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 Quote Link to comment Share on other sites More sharing options...
Bryan Posted April 14, 2004 Share Posted April 14, 2004 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 Quote Link to comment Share on other sites More sharing options...
Dan Iacovelli Posted April 14, 2004 Share Posted April 14, 2004 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. Quote Link to comment Share on other sites More sharing options...
Serguei2 Posted April 14, 2004 Author Share Posted April 14, 2004 Thanks everybody I also downloaded the Stella programmer's guide. It might help me to make my own 2600 games. Serguei2 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 14, 2004 Share Posted April 14, 2004 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 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! Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted April 14, 2004 Share Posted April 14, 2004 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-bin/view/Sandbox/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. Quote Link to comment Share on other sites More sharing options...
Artlover Posted April 14, 2004 Share Posted April 14, 2004 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 14, 2004 Share Posted April 14, 2004 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. Quote Link to comment Share on other sites More sharing options...
Bryan Posted April 14, 2004 Share Posted April 14, 2004 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 Quote Link to comment Share on other sites More sharing options...
kisrael Posted April 14, 2004 Share Posted April 14, 2004 Thanks everybodyI 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) Quote Link to comment Share on other sites More sharing options...
Serguei2 Posted April 14, 2004 Author Share Posted April 14, 2004 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 Quote Link to comment Share on other sites More sharing options...
ErikM Posted April 19, 2004 Share Posted April 19, 2004 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. 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. Quote Link to comment Share on other sites More sharing options...
EricBall Posted April 20, 2004 Share Posted April 20, 2004 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/tutorials/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/tutorials/vflag.html for more on the oVerflow flag. On a related note, IN_ and DE_ also do not change the Carry bit. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 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 Quote Link to comment Share on other sites More sharing options...
Bryan Posted April 20, 2004 Share Posted April 20, 2004 I don't think the compare instructions affect V. -Bry Wrong (See http://www.6502.org/tutorials/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/tutorials/vflag.html for more on the oVerflow flag. On a related note, IN_ and DE_ also do not change the Carry bit. Quote Link to comment Share on other sites More sharing options...
ErikM Posted April 20, 2004 Share Posted April 20, 2004 Wrong (See http://www.6502.org/tutorials/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...? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 20, 2004 Share Posted April 20, 2004 CMP, CPY, CPX do influence the V-flag. http://www.chez.com/apple1/Apple1project/D...2%20Opcodes.htm Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted April 20, 2004 Share Posted April 20, 2004 Hi there! CMP, CPY, CPX do influence the V-flag.http://www.chez.com/apple1/Apple1project/Docs/m6502/6502-6510-8500-8502%20Opcodes.htm Actually, the link that you give agrees with me that the compare instructions don't affect the V flag. Greetings, Manuel Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 20, 2004 Share Posted April 20, 2004 Then just write a simple program and test it on real hardware (or trust the emulators). Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted April 20, 2004 Share Posted April 20, 2004 Hi there! 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 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 20, 2004 Share Posted April 20, 2004 Ok, then someone should correct the wrong documentations. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.