BRANCHING IN ASSEMBLER - START INFO - PART 2 -------------------------------------------------------------------------------------------------- TOOL: Built-In ML-Monitor {Commodore C128} Language: Assembler Extra: none Author: Misel Zivanovic Note: (C) 15th DEC 2025 - www.lived.ch, mzretro.ch --------------------------------------------------------------------------------------------------- THERE IS MORE BUT WE WILL START WITH THESE FELLOWS HERE: BCS - Branch if the actual accumulator value is BIGGER than the compared value. BCC - Branch if the actual accumulator value is SMALLER than the compared value. BEQ - Branch if EQUAL to Zero BNE - Branch if NOT EQUAL to Zero We already had BCC, BEQ and BNE which is branching as long as the result isn't ZERO or NOT true in that case! We won't do regular examples, but a bit more modern style state-of-the-art shows! ;-) That way you will learn how to use them together/combined! EXAMPLE 2: ALL TOGETHER NOW -->>> BCS, BCC, BEQ BNE branch brothers! This code is long, but it's actually containing just a little update to involve also the rest of the branch gang. What's new? BCS is used to visually show how much is wasted or better said, how many numbers were above our 160 characters limit {or 4 rows} Text and Color are using the same indicator routine. {yes, i could've do this separately... But that's your job!} I did not mention this in PART 1, but you surely have notice this already. We are NOT using $1300! We went to $0b00 {dec 2816}. The idea was to show how there is more free and useful space for assembly lines. I will continue with this strategy. Just saying! Now back to work! As in PART 1, here is what need to be done. FIRST STEP : ------------ Type-in this BASIC part or copy/paste it {VICE C128-Emulator} 10 bank 15 15 scnclr 20 char 1,10,10,"press/hold any key!" 25 char 1,11,12,"run/stop to quit!" 30 for a=1 to 1024 40 sys 2816 50 next DO NOT RUN IT YET! SECOND STEP : ------------- You could type in this too, but i suggest to copy/paste it, as you have probably done with the BASIC part above. Keep in mind. It is the Machine-Language code and first you must open the built-in ML-Monitor with the MONITOR command. m b00 b5c >00b00 a9 ff 8d 0e d4 8d 0f d4:I...T..T >00b08 a5 d4 c9 58 f0 fa a9 80:ETIxPZI. >00b10 8d 12 d4 ad 1b d4 aa c9:..TM.TJI >00b18 a0 90 03 b0 1e 60 9d 00:...P.... >00b20 04 9d a0 04 a9 80 8d 12:....I... >00b28 d4 ad 1b d4 aa c9 a0 90:TM.TJI.. >00b30 03 b0 08 60 9d 00 d8 9d:.P....X. >00b38 a0 d8 60 a9 51 8d 68 06:.X.Iq.H. >00b40 ee 3e 0b ad 3e 0b c9 6c:N>.M>.IL >00b48 f0 01 60 a9 20 a2 00 9d:P..I B.. >00b50 58 06 e8 e0 14 d0 f8 a9:x.H..PXI >00b58 58 8d 3e 0b 60 00 00 00:x.>..... --------------------------------------------------------------------------------------------------------------------------------- ALL EXPLAINED: {the same text like in PART 1 as a reminder!} Now let's check what do we have here and what it is doing? BASIC part is pretty much very clear. No need to explain it. Our focus is on the assembly part. Old C64/C128 user will immediately notice the SID-CHIP addresses and its involvement in order to get the random numbers! 54286/$040E Frequency register for voice 3 (low byte) 54287/$040F Frequency register for voice 3 (high byte) 54290/$0412 Control register for voice 3 54299/$041B Voice 3 oscillator output Ergo, SID-CHIP is used to generate/get random numbers. Additional info: This will also work with C64. It is the same routine. However, the same assembler routine coming from C64, will not work with C128! Now you wonder, haha...! Here is why! -> It is because default C128 BANK is 0, but to get the random numbers from the SID-CHIP, your C128 must be set to BANK 15 We are using here BASIC command BANK 15 to set this! To do it in assembler you practically need to additional lines: lda #$00 sta $ff00 This is setting BANK 15 as default in assembler {in RAM BLOCK 0} We will talk about RAM-BLOCK{s} in due time. Okay, now it is clear, let's continue! . 00b00 a9 ff lda #$ff Accumulator value #$ff, dec 255 . 00b02 8d 0e d4 sta $d40e Write to low . 00b05 8d 0f d4 sta $d40f and high byte of the frequency register . 00b08 a5 d4 lda $d4 This register {dec 212} is doing something completely else. . 00b0a c9 58 cmp #$58 It is holding the keyboard matrix value of the button we are pressing. . 00b0c f0 fa beq $0b08 Default value is #$58, dec 88. If nothing is pressed, it will go to check it again! . 00b0e a9 80 lda #$80 As soon as something is pressed, it will go here and the program execution continues. . 00b10 8d 12 d4 sta $d412 We are putting the value from above #$80, dec 128 into control register . 00b13 ad 1b d4 lda $d41b and are loading the value from the oscillator to accumulator . 00b16 aa tax then we are transferring that value to X-register! {used for {$0400,x}, = $0400 + x} . 00b17 c9 a0 cmp #$a0 If accumulator value was less than #$a0, dec 160 . 00b19 90 03 bcc $0b1e we are brunching to $0b1e and are writing the result to $0400+x, $04a0+x {screen} . 00b1b b0 1e bcs $0b3b If the accumulator value was higher then we go to $0b3b . 00b1d 60 rts Not really needed, but it is difficult to edit with ML-Monitor! Write NOP instead if you wish! . 00b1e 9d 00 04 sta $0400,x This is the screen start address + x, left upper corner {1st 4 rows, 160 characters} . 00b21 9d a0 04 sta $04a0,x The next screen address + x, 5th row to continue the sequence, 5-6-7-8, 4x40 = 160} . 00b24 a9 80 lda #$80 Then we are generating/getting a new number for the color registers . 00b26 8d 12 d4 sta $d412 - . 00b29 ad 1b d4 lda $d41b - . 00b2c aa tax - . 00b2d c9 a0 cmp #$a0 You notice how we are able to use color values over #$0f, dec 15 {16 incl. zero} because . 00b2f 90 03 bcc $0b34 #$10, dec 16 {17 incl. 0} is reset to 0 {black color}. All < #$160 is a branch to $00b34 . 00b31 b0 08 bcs $0b3b All numbers higher than > #$160 we jump to $0b3e . 00b33 60 rts Not really needed, but it is difficult to edit with ML-Monitor! Write NOP instead if you wish! . 00b34 9d 00 d8 sta $d800,x This is the color map of C128 {same as on C64}, dec 55296 - 56295, hex $0dbe7} . 00b37 9d a0 d8 sta $d8a0,x 5th row of the color map + #$a0, dec 160, {4 rows, 5-6-7-8} . 00b3a 60 rts Back to BASIC! FOR-NEXT-LOOP until it ends. . 00b3b a9 51 lda #$51 Our little ball! . 00b3d 8d 58 06 sta $0658 Start position of the little ball! . 00b40 ee 3e 0b inc $0b3e Increment $0b3e {NOTE, that is the LOW Byte of the little ball position!!!} . 00b43 ad 3e 0b lda $0b3e Now we load the value of $0b3e because we want to know what's going on there! . 00b46 c9 6c cmp #$6c Do we have there value of #$6c {that's #$58 + #$14, dec 20 = our little balls} . 00b48 f0 01 beq $0b4b If we do have reached #$6c {or our length of 20 balls, jump to $0b4b} . 00b4a 60 rts Otherwise back to BASIC where the FOR-NEXT-LOOP is running . 00b4b a9 20 lda #$20 We jump to here to delete our 20 balls {20 here aren't 20 balls!} That is dec 32 or SPACE!} . 00b4d a2 00 ldx #$00 X-register as counter to 0 . 00b4f 9d 58 06 sta $0658,x We start deletion from $0658 + x . 00b52 e8 inx increment counter . 00b53 e0 14 cpx #$14 Is it already #$14 {or dec 20, our little balls} . 00b55 d0 f8 bne $0b4f No? Well, go back and try again! . 00b57 a9 58 lda #$58 Because we have incremented the LOW Byte of our ball location, we need to set it back to default . 00b59 8d 3e 0b sta $0b3e to start from scratch! Remember $0658 was the address, LOW Byte is #$58, HIGH Byte is #$06 . 00b5c 60 rts Wenn done, BACK TO BASIC and LOOP until the LOOP ends! --------------------------------------------------------------------------------------------------------------------------------- That was not so difficult at all! Now quickly to mention this part: . 00b19 90 03 bcc $0b1e we are brunching to $0b1e and are writing the result to $0400+x, $04a0+x {screen} . 00b1b b0 1e bcs $0b3b If the accumulator value was higher then we go to $0b3b . 00b1d 60 rts Not really needed, but it is difficult to edit with ML-Monitor! Write NOP instead if you wish! Why RTS isn't needed? Why it will work if you just replace this with NOP {No OPeration} Because we have just TWO possibilities. If it is LOWER, go LEFT! And if the number is HIGHER, go right! So the first command below BCS will never be executed in our case... And then also this here to understand it better: . 00b3d 8d 58 06 sta $0658 Start position of the little ball! . 00b40 ee 3e 0b inc $0b3e Increment $0b3e {NOTE, that is the LOW Byte of the little ball position!!!} $0b3e is nowhere to be seen here, but it is right after the $00b3d... 8d {STA TOKEN} = $0b3d 58 {LOW BYTE } = $0b3e 06 {HIGH BYTE} = $0b3f And logically, the first address below is then $0b40 because after 'f' a zero is coming! {0-1-2-3-4-5-6-7-8-9- A- B- C- D- E- F-10-11-12-13-14 etc.} {0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20 etc.} ---------------------------------------------------------------------------------------------------------------------------------