In 6502 assembly language, branch instructions use signed 8-bit relative offsets that range from -128 to +127, encoded using two's complement notation where the most significant bit (bit 7) serves as the sign bit; positive values (0-127) have bit 7 as 0, while negative values (-128 to -1) have bit 7 as 1 and are calculated by subtracting 256 from the unsigned value, enabling efficient relative branching within a limited memory range.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Modern Beginning Assembly Language Programming on the C64: Part 2Added:
Hello everyone. Welcome back to another episode of coding with culp. As always, it is a great day to learn how to code.
And today we're going to be uh doing episode two in my series on beginning modern assembly language programming on the Commodore 64 and the 6502 processor. If you haven't seen episode number one, I highly recommend that you go do it before you watch this one. In episode number one, we go over the tools that we're going to use, the assembler, the um text editors and integrated development environments and um installing a vice device emulator.
Um once again, real quick by modern assembly language programming, what I mean is we're going to be using a modern machine such as a Windows machine, a Linux machine, or a Mac. and we're going to be writing and editing and assembling the code with a cross compil excuse me cross assembler called 64 task. From there we can then put it to a um um emulator such as Vice or we can transfer it to a real com 64 like you see running down here in the uh lower right hand screen. That's my Commodore 64 Ultimate and it's being streamed over my network uh right to OBS. It's pretty cool. If you don't have a Ultimate, I highly recommend them. I'm going to be doing some things that only the Ultimate can do sort of. You'll see here in a bit, but if you don't have a Commodore 64 Ultimate, don't worry about it. Uh, you'll get along just fine without it.
But like I said, awesome machine. This video is late because I've shot it like 25 times and I haven't been happy with any of them. And then I finally I spent all day Sunday, that was yesterday, um, shooting the video, assembling it, editing it, putting it all together. And then I thought it was just too long. it was close to an hour and I I just didn't want it to be that long. And uh so here I am shooting it again trying to make it shorter and more concise. Um what I wanted to do is I wanted to change the program that we made in episode number one by quite a bit to do uh stuff such as this. We can move the hello world around. Um we can change the text color.
We can change the border color like this. and the screen color like that uh using keystrokes. Oo, it's all gray.
Try something different there.
Anyways, um I'm not going to get to that. So, I will get to it uh in video number three. So, in this video, what we're going to do is we're going to make our program number one much more efficient. So, if you remember, let me get this running.
If you remember, program number one was pretty inefficient. What we're essentially doing is poking the uh values for each letter into screen RAM and each color into screen RAM one at a time. And that's that's just not a great way to do things. In addition, um it takes up 109 bytes. So what we're going to do in this video is we're going to take a look at looping um indexing and we're going to learn a little bit about uh signed 8-bit values and twos complement um or well basically signed 8-bit values we store in what's called uh tw's complement notation. So let's just go ahead and and get started. And what I wanted to do, I wanted to start out by taking a look at um how the um assembler puts this into memory and disassemble that first program.
So what I'm doing here is I have on my um 64 Ultimate um there is a web control interface and it's really cool. allows you to do lot lots of stuff like drag SID player or SID tunes over um PRG files and CRT files and run them uh directly across the network. You just drag it and it transfers it to the uh 64 Ultimate and runs it or plays it, etc. There's even a basic editor where you can uh type in code and then upload it and run it. Um you can also, which is what I prefer to do, use an editor and then copy and paste it in and upload it.
But what we're concerned about here is the live monitor. And being able to work a monitor is an essential skill when you are programming in assembly language on the Commodore 64. The monitor allows us to get a live look into the memory of the Commodore 64 and what's going on. We can get memory dumps.
We can disassemble what's there, which is, as you might imagine, the opposite of assembly. It's going to take the raw bytes, the raw data, and then interpret it as as code.
And uh there's a few different ways that we can do this. Um in the old days, you would run something like Hessmon or 64mon and do it directly on the Commodore 64. One of the issues with that though is that it takes up its memory resident on the Commodore 64 and it takes up memory on the C64 that you might need. Whereas doing it this way, um it doesn't take up any memory on the Commodore 64. So that's what we're going to do. And so let's pull up our program real quick. And let me bring it to here.
Let's type help right here. Oh, let me also make the Commodore 64 screen much smaller.
There we go. So hopefully it's not getting in the way now. So if we type in help, it tells us the available commands is we can type in M to get a memory view. And that's the raw memory. And if you remember, this uh starts at 033C. So we go from 033 C to 03 A8. So we go M33 C to 03 A. Instead of eight, I'm going to go to uh nine. [snorts] And when I do that, that's a raw memory dump of um what's in memory uh in that area.
[clears throat] Doesn't seem to make a whole lot of sense to us. It's just a bunch of hexodimal numbers. Instead, let's get a disassembly.
And so we're going to do the same thing only we're going to hit the d command to disassemble.
And so now what it does is it takes those uh raw bytes that raw data and attempts to convert it back into code.
So let's take a look here.
All right, let's scroll down which uh once again remember all this is constants here. It doesn't take up any uh memory in our com 64s program. Um it's basically a onetoone substitution when we assemble. But our code begins here at 033C.
And uh our very first instructions are load the accumulator in immediate mode um with the value of 93 hex 93. And you'll notice right there that corresponds to that right there. And this is um 033C. So that is memory address 033C right there. So that A9 corresponds to load the accumulator.
That is the op code or LDA or load the A register or accumulator in immediate mode. Remember immediate mode means that we're going to use that actual literal value there of 93. We're going to put that into the accumulator. And right there at 033D is our 93.
And then you'll notice that the very next thing is load the accumulator. Um, oh no, I'm sorry. It's JSR char out. And sure enough, there it is right there.
And, uh, if you remember, char out is the kernel routine that outputs a character on the screen. We stick a character in the accumulator and we call char out and it puts it on the screen.
And its address is FFD2.
So what this does is it's going to jump out to memory location FFD2 and execute that code and then come back. And so we got JSR and 20 is the op code for JSR.
And then we got FF D2. No, we don't. We got D2 FF. That's kind of weird. It's it's backwards.
So that's strange. I wonder what's going on. Did something Did something go wrong? And the answer is no.
The Commodore 64, the 6502 processor inside the Commodore 64 is what's known as a little Indian processor.
And what that means is it's how the Commodore 64 is expecting a value a 16bit address in memory.
And so what we've got here in the 16- bit address FFD2, the D2 is what we call the low bite because it has the lower value and FF is the high bite. It has the higher value.
And this is called a little Indian processor because it expects the little bite to be first in memory. And so if this right here represents our memory address, okay, or our little boxes in memory, each one a bite, the 6502 processor expects the little part or the low bite to be first in memory or lower in memory at the lower memory address and uh FF or the high bite to be second.
And it's just the way it goes out to grab that memory address. And we don't have to worry about it. You'll notice we we didn't have to do anything. The assembler knew that and did that for us.
On occasion, if we have to put a 16- bit memory address into memory manually, which we might have to do on occasion, we need to remember that that the 6502 is a little Indian processor and it's expecting the D2 to be first and the FF to be second in memory. Consequently, the uh Intel x86 uh architecture is little Indian. And as you might imagine, there's also big Indian processors, the 68,000 or 68K, which the um AmIGGA was based off of and the original Max. Uh and also, I think Power PC processors are big Indian processors, and they're expecting the big part to be first.
All right. So, I'm not going to go through uh all of it. Um the rest of it's pretty self-explanatory. If you understood that, you understand the rest of it. Um once again there's that store accumulator in store the accumulator into memory and the memory address is screen RAM plus 019A and so that corresponds to address of 059A which it puts in as 9A5. Last thing I want to take a look at here is at the very end and that is our uh jump instruction. Let me bring it closer to the center here and let's scroll down.
Scroll down. Scroll down and right there it is um at address 03 A6 and that's our jump instruction right there. And so this um label right here forever, it corresponds to that memory address of 036. And once again, we didn't have to calculate it.
Um the assembler did it for us. And that's what's so great and nice about assemblers. And you'll notice, so uh we've got jump jmp and um this is the op code for jump 4C right there. And then we go to 0386 03 A6. But notice it, it literally jumps back to itself.
And so this is just a a super tight super tight loop. And um um it's going to go forever. It's a classic um infinite loop. So, I hope that uh helped out a little bit and hope hope that uh you know helped seeing kind of what's going on when it assembles and puts it into memory. Now, like I said though, this really isn't a great way to do this simply because um a that's a lot of code to write to get hello world and and b it takes up 109 bytes. So, I've got P3, uh, hello.asm right here. And you're probably wondering what happened to P2. Don't don't worry about it. Um, and let's run it on my ultimate over here.
[clears throat] And there it is. Hello world. Now, one thing you're going to notice, unlike the other programmer, we had to type in CIS 828 ourselves.
This actually has a basic loader, a basic stub in it, and it automatically puts 10 CIS 2064 in there for us. So, now all we got to do is type run.
So, we're going to talk about how to do that in just a minute. But the other advantage of doing it the way we're about to is that it takes up a whole lot less memory. So, let's assemble this thing P3.
and it takes up we got 12 bytes of data and that's our our little um basic stub.
I'll talk about that in just a minute. A gap of three bytes. I'll talk about why that three bytes is there in just a minute. And then 46 bytes. So our program actually takes up 46 bytes. So 46 plus 15, what is that? 61 bytes.
That's quite a bit um shorter than our 109 bytes that the other one took up. So let's talk about it. Um all this up here should look familiar to you. It's pretty much the same. These are constants that we've defined. Um, however, we've got a new kernel routine right here um called plot at ff0.
Let's take a look at what plot does.
Also, let me increase the size of our comra 64 window.
Okay, so plot is a kernel routine located at fff0 or 65520.
And when this routine is called, it's going to either get or set the cursor position based on the status of the carry flag. We'll talk about the carry flag at great length later on, but it's essentially a um memory location inside of the 6502 processor that's part of the status register.
And we can set and clear the stat the carry flag uh if we want to. So, um, we'll we'll we'll have to set the carry flag or clear it, excuse me, if the carry flag is cleared before calling the function. The cursor is going to be set to the position specified in registers X and Y. The value of the X and Y register are preserved. So, whatever we put in X and Y isn't going to go away. But the value in the accumulator is going to be overwritten. And that's important to know simply because if we have a value in the accumulator that we want to keep before we call the plot function, we're going to have to save that value. We're not going to have to worry about it in in this program though. So basically, we'll clear the carry flag. We'll load the X and Y register with the position we want and then call the plot function.
If the carry flag was set though before calling it, then the cursor position is going to be put into the X and the Y registers. And now this is a little backwards to me. The X register represents the row. So we'll put the row value in the X register and the Y register represents the column. Seems backwards to me um because the row is how far down the screen we want. And it seems to me that's more of a ycoordinate.
And the column is how far across the screen it is. And it seems to me that's more of an x um coordinate. But you know, whatever. I'm sure there was a very good reason why they did it this way. Then we've got this thing right here. We've got a new thing called cur color, which stands for cursor color, and it's at address 0286.
If you look at a com 64 memory map, let's pull one up real quick.
Oh, let's see here. Where is it? What did I do with the memory map? Right there it is. Uh, let me see if I I can do a find.
F uh 02 86.
And there it is. Right there. 0286 is the current color. The cursor color.
It's basically it represents what um color the text is going to be drawn in.
or printed in when we printed the screen. And so we can put a color value in that address and it's going to use that to write uh text onto the screen when we call the char out routine. Now we get to something uh completely new in this basic stub right here. This really isn't assembly language. Uh what we're doing is we're literally manually poking or forcing a line of basic code into the Commodore 64's memory. And and in order to do that, we need to know what a line of basic code looks like inside the Commodore 64's memory.
And so the first two bytes, when we're talking about a line of basic code, the very first two bytes are a pointer to the next line of basic in memory.
And so here's how I accomplish that here. So this means, hey, we want a word value. A word means two bytes.
And we want that word value to be the address of this label right here called next, which is right here. And this label occurs right where the next line of basic would be. So this address is going to literally be the next line of basic code. And so this word value, these two bytes, it's going to put in the address of next, which is going to be the address of what would normally be the next two basic or the next line of basic code. Um if you're an experienced coder, you might realize that uh in reality basic the basic lines in the comm 64's memory are really a linked list of lines which which the uh with the beginning of each line pointing to the next line in memory. I just happen to know that the next line is going to be at 080 in memory and 08.
So basically what gets put into here is 08 OB and uh or 08 OB. Um this right here that's the next address.
All right. Now we can begin our basic line.
Every single 64 basic line the first two bytes are going to be the line number.
And so once again we tell it hey let's put in a word value which is two bytes and decimal 10. So our line number is going to be 10.
Then the rest of it is the actual line of basic. And uh what we're going to do is um we're going to poke in dollar sign 9E. Okay. Or one bite token code for CIS. And then somehow someway I have deleted a line of code. So let me put that back. Uh right here we should have text. So I don't know what happened to it.
2064.
There we go. All right. So then we got four bytes or 2064.
So we're going to poke in the values for 2 064.
And that's what this is going to do.
then every single basic line ends with a null terminator, a zero. And so that's what that does.
Then once the line is done, normally we would have the next basic line.
However, if there are two null bytes in a row after a basic line, that signifies to the commerce 64's basic interpreter that that basic program is done. It's finished. There's no more lines.
So, we've got 2 4 5 9 10 11 12. We have 12 bytes for our um basic stub. And if you remember, let's come over here. Um, it tells us that we have 12 bytes at the beginning.
And that's what those 12 bytes are. And then we skip three bytes. So in reality, okay, we're going to begin at address 2064.
Um, but in reality, I could have done 2061 and then I would have also had to uh subtract three uh from here.
However, um it's kind of traditional in Comm 64 basic that it's a 2064. So that's what I did. If you really need those three bytes, you you can change it. So once again to recap, every single uh basic line begins with a two byte pointer to the next line of basic.
Then we have two bytes for the line number.
Then everything after that is the actual code for uh that basic line. Um 9E corresponds to the token code for CIS.
And then we have 2064.
Um that's going to come right behind it.
Notice I don't have a space because it's not needed. Um and then every basic line ends with a null terminator, a one by zero. And then if it's the end of the basic program that um um next line is going to have two zeros um two zero bytes and that signifies to the kernel hey or the basic interpreter hey we're done. So I hope that made sense. So now we have our actual code and we're going to start at 0810 or address 2064.
And this part should look pretty familiar to you. Uh that's what clears the screen. Uh 93 is the screen code for clear home and we pop it out on the screen that's going to clear. Now we got the new stuff. Now if you remember our plot routine, we got to set the row and column. So we're going to set the row LDX, okay, in the X register uh to 10.
And so that's hexodimal 0 A, which by the way, I don't know if I need to go over number bases like hexodimal and binary in a in a video. let me know if I need to. And then we're going to put 10 in the Y register. And then remember, we have to clear the carry flag. And that's what this does. CLC clears the carry flag so that it's telling the plot routine we want to set it. And then we JSR plot.
All right. Now, this should look familiar. We're going to start out with white. We could change this to whatever uh color we wanted to. And we're going to store that though into the address for cur color or current color. And you know one thing you got to realize is that this right here is not a variable in a traditional programming language.
This is a memory address. Cur color corresponds to a memory address. So when we store the accumulator or store the A register, it's going to go out to that memory address pointed to by cur color which is um 0286 and it's going to drop in this value for white which is one into that memory address.
And now we get to kind of the meat and potatoes right here, this uh LDX. So what we're going to do, let's come down here. There's something new down here.
And once again, this is not a um variable in a traditional sense of the word for a traditional programming language. This is a labeled, we can think of it as a labeled address. What's going to happen is the assembler is going to figure out where this is in memory. Okay? And whenever we we refer to message like we do up here, that's a memory address.
And so message actually points to or that memory address has the letter H or the value the uh PKY value for the letter H capital H which I think is 48 if I remember off the top of my head. So that means that memory address that corresponds to this label it has the number 48 in it and that's in hex by the way.
So what we do is we load the accumulator with whatever is in the memory address for message which is going to be 48 offset or indexed by whatever's in the x register which right now there's a zero in the x register. So, it's going to take this memory address and it's going to [clears throat] add zero to it. And that corresponds to the H to that memory address right there. Now, we get something else that's kind of weird.
Branch if equal be Q forever.
So, what this means is branch if the Z flag or the zero flag is set. I really wish that they that they had named these branching instructors instructions a little bit different. Now you're probably thinking the zero flag, what are you talking about? What branch of equal does is it reads the zero flag.
And once again, like the carry flag, that's a flag or a single bit inside of the status register.
And the Z flag or zero flag is set if an operation results in a zero value.
And one of those things that can set the Z flag or the zero flag is putting a zero directly into the accumulator.
Well, we didn't do that. We put a 48 into the accumulator because that's the H there. And so that's not going to set the Z flag. the Z flag or the zero flag is going to be cleared. So, we're not going to branch if equal. The Z flag is not equal to zero. So, that means we're going to fall through to this JSR. And the JSR is char out. It's going to go, it's going to put um H on the screen at the current cursor position.
Then, we're going to increment X. So, that's just going to add one to X. and x is going to now be equal to one. Which by the way, we can't really do a whole lot of arithmetic in the x and y registers. This is pretty much it. We can increment it by one. We can decrement it by one.
Then what we do is we drop through to B and E. B& E stands for branch if not equal. In other words, branch if the Z flag is not set. Well, the Z flag is not set. So, we're going to branch back up to print loop and we're going to do it again, but now there's a one in the X register. So, we're going to take the memory address for message and we're going to add one to it. And that's going to give us the memory address for E.
And we're going to do the same thing.
Branch if the zero flag is set. Well, it's not set. We didn't put a zero in the accumulator or the operation we did did not result in a zero. So the zero flag's not going to be set. We're going to pop that E out onto the screen. We're going to advance to cursor position.
We're going to increment X. It's going to be equal to two. Now we're going to branch if not equal. Well, the Z Z flag is not set. So we're going to go back up to print loop. We're going to keep doing this over and over again. We're going to get an L, an L, an O, space WL D. But notice right here, we've got this bite value zero. And in reality, what it does is it puts it in the memory location right behind the D. There's going to be a zero there. And so what's going to happen is eventually X is going to be equal to, let's see here, 0 1 2 3 I'm counting wrong. 0 1 2 3 4 5 6 7 8 9 10 11. Eventually, it's going to be equal to 11. So we're going to take the memory address for message, which is the H.
We're going to add 11 to it and that's going to give us that zero.
So what's going to happen is when we load the accumulator with message + 11, the accumulator is going to get a zero put into it. That sets the Z flag. That sets the zero flag. And so now we're going to say branch of equal branch. If the Z flag is set, branch of equal to zero, we're going to branch to forever.
That ends our program and we're just going to loop forever and ever and ever.
By the way, this has a name. It's called a null terminated string. There's a few different ways we could have done this, but this is probably the easiest. And null terminated strings are common in other programming languages such as C and C++, etc. All right, I hope I hope that made sense. We're going to take a look at it in memory again. So, let's do that. Let's uh let's bring up our um so let's look at this 081 to 08 real quick.
Um, so, um, I'm going to disassemble from 0801 to 080. I'm going to go one once again one or two more. I'm going to go to 08.
There we go.
And you're going to notice um, this does not look like um, you know, code.
This is junk right here. But this is our basic stub. So, let's take a look real quick.
I think I went too far. That's [laughter] It's okay. I think I put the whole program in there. All right, let's look at a basic stub. So, if you remember, uh, we're going to have two bytes for the pointer to the next basic line, which I already told you was 08 OB. And sure enough, there it is. OB8 because it gets put in there in little Indian format. Uh, next is a word value.
Two bytes for 10. Uh, 10 is OA in hex.
And then we have 0 0. So that's our two bytes 9E and then uh 2 0 64.
These are the um um het key values for 206 and four in hex. Then we've got a single zero bite to say hey this line is done. And then we have two bytes right there to end the basic program. And then what we've got is let me clear that.
So let's see here. Uh that that and that. Okay, we got three bytes. One, two, three. Those are those those three bytes that we skipped. And then our program begins right there. And sure enough, load the accumulator 93 is right there. Let's take a look at uh some more of this program because there's some stuff I want to go over with you.
So, um, all this should be pretty pretty easy to understand. I'm not going to go over it. What I want to do is I want to go down to our actual, uh, print loop at the LDX 0. And there it is right there at 0822.
So, we're going to load the accumulator or load the X register, excuse me, with 0. And that's that right there. And then we load the accumulator with uh, 0832 um, offset by X. Uh, let's look at 0832.
So 0832 is right here. And 48 is an H. I was right. H E L L O space W O R L D.
And that's our zero terminator. Our no excuse me, our null terminator right there in memory.
But now we've got something weird that doesn't seem to make sense.
Um our branch of equal instruction. So you remember branch of equal branches if the Z flag is set. And so there it is right there. Branch of equal. And we're expecting it to branch to a memory address. Um in fact we're expecting it to branch to forever which is uh let's see B& print loop. So that's right right there. So we're expecting it to branch to 082F.
But it doesn't. branches to hexodimal 06.
What's going on here? Here's the deal.
Branch instructions are relative or um their jumps are relative. Um it's from that memory location. And so what that means is this is a signed 8bit number.
Let's talk about signed 8-bit numbers so you can understand what's going on right here.
Let's talk about signed and unsigned 8-bit numbers. And in reality, everything I do here say here applies to signed or unsigned 16- bit values, too.
Um, this is one of those things that I really think you do need to understand in 6502 assembly language. There there are things that I I think are optional.
For example, I I don't really think you need to truly understand hexodimal values in today's day and age. you can, you know, use a calculator to um convert back and forth or, you know, just type it into Google or whatever. Um, however, I I absolutely believe that you you need to understand signed 8bit numbers or signed and unsigned 8-bit numbers. So an unsigned 8bit value has 256 different values and they range from 0ero to 255 um which is 00 to FF and hex.
A signed 8bit value or a signed 8bit bite also has 256 different values just like an unsigned 8bit bite but they range from negative 128 up to positive 127. And if you do the math that is in fact 256 different values. What that means is for our branch instructions like B& and BEQ etc. Our branch instructions are once again they're relative. And so that means they can jump or branch I'm sorry wrong terminology there. They can branch up to 128 memory locations backwards from the location and 127 memory locations forward.
That means they don't actually have access to the entire range of the Commodore 64's memory. And you can easily write code where you're trying to branch to a location that is outside of that range. And then usually what you have to do is you have to branch you you do a near branch to a um um label and then jump from there because the jump um instruction has access to the entire 16bit range of the Commodore 64's memory. So just remember that. And if you assemble something and you get a branch out of range, you're going to have to do something like um branch to a um label that you make and then from that label then jump elsewhere in memory. And you see that all the time in 6502 code. Um so our 0 to 127 values are 00 to 7 he 7f in hex and negative 128 to negative one which is 80 to FF. And that that that sounds weird because well FF is absolutely not equal to -1. So let's let's find out how we get those values.
First of all, um, bit seven in a signed um, 8 bit value, bit seven, the most significant bit is the sign bit. And we use something called TW's complement encoding to encode a signed 8-bit value or 16 bit value. I keep saying 8 bit, but in reality, this works with 8 bit, 16 bit, 32-bit, whatever.
And here's the deal. If bit seven is a one, we consider that to be a negative number.
And if bit zero or bit seven is a zero, we consider that to be a positive number.
So let's take a look at some examples and how we convert.
So right here we've got all zeros for the binary. Well, that would work out to zero hex. [laughter] And because bit 7 is a zero, this is positive. And so it's signed and unsigned values are exactly the same.
Um, same thing over here. We have the least significant bit set and the most significant bit is not set. Therefore, this is a positive value.
So we just work it out as normal. That's going to be hex one. and its signed and unsigned values are exactly the same.
Over here, we've got all the bits set except for the most significant bit. And once again, because the most significant bit is a zero, this is a positive value. And we just add up all the bit values just like normal. And we get 7F, which is 127. And because it is a positive number, its signed and unsigned values are exactly the same. By the way, I've been going back and forth as to whether I need to go over number bases such as binary and hexodimal. If I need to dedicate a video to number bases and uh what they mean and how to read them and how to convert, let me know.
127 is in fact the largest possible signed 8-bit number. Now, let's take a look at what happens if the most significant bit or the sign bit is set.
So, right here, we've got only the most significant bit set and everything else is a zero. And you're probably thinking, oh, well, that's Wait a minute. Is that zero? Is that is that negative zero?
What's going on? Well, in hex, this is um 80 80 hex. If this were an unsigned value, it would be 128. we would just, you know, take that bit right there and that's got a place value of 128. So it value is 128.
And um but that's not what we do with a signed 8 bit value. This is negative 128. And to get that all we do if the most significant bit, the sign bit is set, we're going to take that value, okay, the actual binary value, and we're going to subtract 256 from it.
And there we get -128 which is the smallest possible signed 8 bit number.
Let's take a look at some other examples. Right here we've got everything set except the uh least significant bit. But the most significant bit is set. Therefore, this is a um negative number. This would be FE and hex or 254 if this were unsigned.
But because it's signed, we're going to take that 254.
We're going to subtract 256 from it and therefore we get -2.
Here's one. Everything is set all of them. So normally this would be 255 or FF in hex.
However, once again because this bit right here the most significant bit is set, we read it as a signed value. So it's 255 minus 256 which is negative 1 which is also why negative 1 is true in com 64 basic in pretty much every modern programming language um it sets values for true and false and for most um modern languages one is true and zero is false um and many of them zero is false and anything that's non zero is true and a bunch of other stuff but in com 64 basic and many of the basics of that time -1 is uh the value for true and that's because it corresponds to everything having its bit set in in that bite. All right, I I hope I did a good job of explaining that once again. You got any questions? Um leave them down below. Uh let's jump back in and look at the program. All right, I hope that I hope that made sense. So what's going to happen is branch of equal is going to jump six memory locations forward because this is a positive number. And you can tell that because that right there, the high nibble is not set. So there's definitely a zero in the most significant bit there. And so and in reality, this has to do with the program counter. We're going to go from not this memory address right here, but from this one. One, two, 3, 4, 5. Boom. Right there. 082F is our jump instruction.
Um, so right there. So, we are going from uh load the accumulator. Boom. Down to here. Jump forever. Little bit of a jump cut here because I'm coming back and reshooting this because I don't think I did a good job explaining this part right here. I want to take a look at this B& instruction right here. This branch if not equal to print loop. And we know now that this is a relative address. And that F5 is going to be a jump backwards in memory. And let's take a look at that F5. F5 in um um decim in binary is one one one uh let's see here 0 one 0 one one so that that's F5 with this nibble right here these four bits being the five part and this uh part right here being the um uh F part and so once again this is in two's complement it's a negative number and So right here that tells us that uh because this right here is a one that it is in fact a negative number. So to convert this all we got to do is take a look and see what is the but what is the actual you know uh decimal uh value here.
And let's see here let's work this out.
Um this right here these four right here is 240 + 5. So that's 245.
So the actual decimal right here is 245.
Looks a bit like a one, but anyways, it's 245. And then from that, we're going to subtract 256.
And that's going to give us -1. So, we're going to jump backwards in memory from here. 11 spots. Let's count.
1 2 3 4 5 6 7 8 9 10 and 11. And that puts us at the LDA0832 X, which is this right here, which is exactly where we want to jump back to, back to the top of print loop. So, I hope that made sense. Um, if you got any questions, just ask me down below and I will attempt to uh answer them.
That's it for this video. I wanted to make it as short as possible. Next video, I promise we're going to do some fun stuff. Like I said, we are going to we're going to change our program so we can move this around. We're going to talk a lot more about branching. um and some test, etc. And we'll be able to change colors, change colors, etc., and we're going to respond to key input, etc. The good thing is I already have this shot and I'm pretty happy with it.
So, this will come out here uh real soon. So, until next time, um keep coding, experiment with this, try to change it, do different things, etc.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
🚀 BCS613C Compiler Design | Module 1 to 5 Schema Evaluation 🔥 | VTU 6th Sem 💯 #VTU #bcs613c #exam
Pranavaa-y4y
104 views•2026-06-02











