LOW-HIGH-BYTE-MYSTERY -------------------------------------------------------------------------------------------------- TOOL: Built-In ML-Monitor {Commodore C128} Language: Assembler Extra: - Author: Misel Zivanovic Note: (C) 15th DEC 2025 - www.lived.ch, mzretro.ch --------------------------------------------------------------------------------------------------- Commodore C128 is a fascinating 8-bit Personal Home Computer, however his address space is 16-Bit and not only 8-bit, which would give us a values of #$ff, dec 255 So its highest address is $0ffff, dec 65535 *************************************************************************************************** {Not a subject here, it's just to let you know quickly} There is also a 14-bit VIC-VIDEO-KING inside of the C128! That guy has some small limitations accordingly and uses 4 Video-Banks to master the whole space of 64KB or $0ffff. Which means 65KB of RAM BLOCK is divided in 4 16KB partitions and VIC can see only inside the active partition. e.g. If you change the default value $0400, dec 1024, then POKE 1024,1 will show nothing! You'll have to use the VIDEO-BANK you have set as active! *************************************************************************************************** --------------------------------------------------------------------------------------------------- And back to LOW-HIGH-Byte-Business! Here we go: $0ffff, dec 65535 In order to reach this, Commodore or better said CPU is working with Low and High Byte, also known as a little-endian system. How is the address divided? monitor monitor pc sr ac xr yr sp ; fb000 00 00 00 00 f8 a 00b00 lda +65280 a 00b03 This resulted as: a 00b00 ad 00 ff lda $ff00 Let's check this closer and see what is what! This is actually not just $0b00 as in 10 PRINT "Hello World": COLOR 5,6 It's more like: 10 PRINT "a": 20 PRINT "b": 30 PRINT "c" |------------------> $0b00 | | |---------------> $0b01 | | | | |------------> $0b02 |----| | | a 00b00 ad 00 ff lda $ff00 | | | | | | | | | | | | | |-----> This is our 16-bit address, dec 65280 | | | | | | | | | | | |---------> Here is the assembler command {LDA, Load Accumulator} | | | | | | | | | |------------> That looks like a HIGH-Byte value of the address $0ff00 and it is! | | | | | | | |---------------> And this then only can be the LOW-Byte of $0ff00. Well, both are mislocated, right! | | | | | |------------------> And this is the LDA token value | | | |-----------------------> Our start address, dec 2816 | |-------------------------> And this little princess is THE BANK! {0 - 15 available, just 4 practically usable!} As it clearly can be seen, LOW-Byte is coming first, followed by the HIGH-Byte as second. That's something you always must consider when incrementing the values of the addresses because it can very quickly go into wrong address. Basically it is the opposite of the actual address. Now we know what is what and can say: ACTION! FIRST STEP: ----------- Copy/paste this into BASIC 7.0 {VICE C128 Emulator} list 0 scnclr:char 1,0,0 1 print "hfhedblaklgwoau exlwyu5zkv*e" 2 print "as asdfasfasdfasertwer534vbo" 3 print "dfasdfgasfgasagc43xfasdfsvbw" 4 print "dfasdfg#(#&#(123fwqer)#)0#sg" 5 print "lgkgmhuriemdndheueokdjfhryre" 6 print "cnbvbgyrydk,dkwwutytytueieie"; 7 print "qefsdfghuiyolgbns21k22y33w44"; 8 print "s55k66y77w88a46luokweesdrwb!"; 9 print "ah!dfgertiopzxcsdfdfgghrtyti" 10 sys 2816 SECOND STEP: ------------ Copy/paste this to ML-Monitor of C128 Start the ML-Monitor with the MONITOR command first. When done, exit the MONITOR with X {and press ENTER} Now you can RUN the BASIC part! m b00 b40 >00b00 a9 00 a2 00 ad 00 04 8d:I.B.M... >00b08 08 06 ee 05 0b ee 05 0b:..N..N.. >00b10 ee 05 0b ee 08 0b e8 e0:N..N..H. >00b18 0b d0 e9 a9 00 8d 05 0b:.PII.... >00b20 ee 06 0b ee 01 0b ad 01:N..N..M. >00b28 0b c9 02 f0 02 d0 d3 a9:.I.P.PSI >00b30 00 8d 01 0b 8d 05 0b a9:.......I >00b38 04 8d 06 0b a9 08 8d 08:....I... >00b40 0b 60 00 00 00 00 00 00:........ --------------------------------------------------------------------------------------------------- ALL EXPLAINED: This really just looks complicate {or not}! And here is how we made our TOP SECRET! message become reality out of this mess on the screen! . 00b00 a9 00 lda #$00 This will be our 2nd LOOP counter . 00b02 a2 00 ldx #$00 Counter for the main LOOP . 00b04 ad 00 04 lda $0400 Load values from $0400 to accumulator {we will increment the counter here later. LOW-Byte} . 00b07 8d 08 06 sta $0608 This is the address where we will show the message! . 00b0a ee 05 0b inc $0b05 Increment the LOW-Byte . 00b0d ee 05 0b inc $0b05 again . 00b10 ee 05 0b inc $0b05 again {total 3x} . 00b13 ee 08 0b inc $0b08 Increment the message counter 1x . 00b16 e8 inx Increment the LOOP counter {x} . 00b17 e0 0b cpx #$0b Is it 11? . 00b19 d0 e9 bne $0b04 No! Back to LOOP {from $0b04, NOT $0b02!} . 00b1b a9 00 lda #$00 When loop is finished, we are setting the LOW-Byte to 0 . 00b1d 8d 05 0b sta $0b05 by writing 0 into the LOW-Byte address . 00b20 ee 06 0b inc $0b06 then we increment the HIGH-Byte of the same $0400 location {to be $0500 ->>} . 00b23 ee 01 0b inc $0b01 Increment our second counter by 1 . 00b26 ad 01 0b lda $0b01 Load the value from there . 00b29 c9 02 cmp #$02 and check if it is 2!? {which means 3rd LOOP which we don't need and are going to EXIT! . 00b2b f0 02 beq $0b2f If YES we go to $b2f {EXIT the 2 main LOOPS} . 00b2d d0 d3 bne $0b02 Otherwise we LOOP again $0b02 to reset the x counter! . 00b2f a9 00 lda #$00 We set previously values to default . 00b31 8d 01 0b sta $0b01 here . 00b34 8d 05 0b sta $0b05 and here . 00b37 a9 04 lda #$04 Here we set HIGH-Byte to $04 again = $0400 . 00b39 8d 06 0b sta $0b06 HIGH-Byte . 00b3c a9 08 lda #$08 And we reset old message location to #$08 . 00b3e 8d 08 0b sta $0b08 as it was at the beginning {LOW-Byte} . 00b41 60 rts Back to BASIC ---------------------------------------------------------------------------------------------------