Hello, I'm back, still need assistences

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

DocWaluigean
Posts: 205
Joined: Sun Jun 17, 2018 6:41 pm

Re: Hello, I'm back, still need assistences

Post by DocWaluigean » Wed Jun 17, 2020 7:17 pm

Garth wrote:
Wed Jun 17, 2020 5:59 pm
Chapter 17 of the Eyes & Lichty programming manual mentioned earlier dedicates an entire page to diagramming every one of the addressing modes. It would be difficult for me to do any better than that.

Every instruction has an op code. That's the first byte of the instruction, and in some cases, the only byte. If there's more than one addressing mode available for that instruction, the op code also tells which one. JMP for example has two addressing modes on the NMOS 6502, one being direct, which has an op code of $4C, and the other being indirect, which has an op code of $6C.

Most instructions also include an operand, which is a second byte and possibly a third byte of the instruction. In immediate addressing, the operand is the actual data, and your source code will specify that with the # symbol. An example is LDA #$41, where it puts $41 (ie, the number itself) into the accumulator. The complete machine-language instruction is A9 41, where $A9 is the op code and $41 is the operand.

Without the # symbol, the assembler will lay down the zero-page direct addressing mode version of the LDA instruction, op code $A5 instead of $A9. When the code runs, the processor will read address $0041 to get the data to put in the accumulator, instead of putting the number $41 itself in the accumulator.

Indirects are indicate by parentheses. The NMOS 6502 does not have a indirect LDA without indexing, but the CMOS one does; so just to keep things simpler for now, I'll use the CMOS's one and not get into indexing quite yet. If you write in your source code LDA ($41), the assembler will lay down op code $B2 instead of the $A9 or $A5 used above. When the code runs, the processor will read memory locations $0041 and $0042 to get the complete address of where to find the final desired number. So suppose addresses $0041 and $0042 contain $301B, and address $301B contains the byte $9A. $9A is what gets loaded into the accumulator.

There are many more addressing modes. I think you'll have to go step by step through a good programming manual, and practice. If you have nothing to practice on yet, there are online simulators like the one at http://skilldrick.github.io/easy6502/ which you might try.
That doesn't help me understand sadly... But I'll see the book you provided
The Addressing Modes
There are fourteen addressing modes available to the 6502, all of those plus two more on the 65C02,
and another nine categories available on the 65802 and 65816. Each mode allows the location of the data being
referenced by a given instruction to be specified in a different manner. The availability of many different
addressing modes on the 65x processors is one key to their power.
The data found in operand bytes of an instruction is only one part of the effective address specification;
the addressing modes, expressed using the correct address-mode syntax in the operand field of an assemblylanguage statement, cause the assembler to choose from among the instruction’s possible opcodes to one
specific to the addressing mode. Not all addressing modes are available for all instructions; but there is one
unique opcode for each combination of addressing mode and operation.
The addressing mode is the determinant of the effective address for an operation – the memory address
that the instruction will access for data or to transfer control within the program. For a few of the 65x
addressing modes, the effective address is provided in the operand field of the instruction. But for most of
them, formation of the effective address involves an address calculation, that is, the addition of two or more
values. The addressing mode used with a given instruction indicates where these values are to come from and
how they are to be added together to form the effective address. This effective address calculation has as many
forms as there are addressing modes.
An important aspect of effective address calculation on the 65802 and 65816, to be considered in
addition to the addressing modes themselves, is the state of the x index-register select flag and, to a lesser
extent, the m memory/accumulator select flag, both in the status register. In a sense, the x flag, for example,
extends the addressing mode specification part of an instruction, which uses an indexed addressing mode, by
determining whether or not an eight-bit or sixteen-bit index register is to be used. For every one of the indexed
addressing modes, there are two similar methods of forming an effective address, depending on the setting of
the index-register select flag. Pay special attention to the status and effects of the select flags.
In the following pages are graphic and written presentations of each of the addressing modes,
illustrating the effective address formation, complete with a listing of the processors on which, and the
instructions to which, each addressing mode is available. A sample of the assembler syntax used to invoke each
one is included as well.


It doesn't help about 14 addressing nodes.. Reading it only overwhelms me to think because I'm still beginner in 6502 coding stuff.

And as for EASY6502, I understand everything to the point of Branching page except "BRK", "CPX", and the following:

is the stack pointer. I won’t get into the stack yet, but basically this register is decremented every time a byte is pushed onto the stack, and incremented when a byte is popped off the stack.

PC is the program counter - it’s how the processor knows at what point in the program it currently is. It’s like the current line number of an executing script. In the JavaScript simulator the code is assembled starting at memory location $0600, so PC always starts there.


And reading the next part:
Addressing modes
The 6502 uses a 16-bit address bus, meaning that there are 65536 bytes of memory available to the processor. Remember that a byte is represented by two hex characters, so the memory locations are generally represented as $0000 - $ffff. There are various ways to refer to these memory locations, as detailed below.

With all these examples you might find it helpful to use the memory monitor to watch the memory change. The monitor takes a starting memory location and a number of bytes to display from that location. Both of these are hex values. For example, to display 16 bytes of memory from $c000, enter c000 and 10 into Start and Length, respectively.
I know this part, about the Addressing locations and memory stuff of Address Locations. So I feel like we're on the wrong side of something of misunderstanding.

Also,
For example, to display 16 bytes of memory from $c000, enter c000 and 10 into Start and Length, respectively.
I'm confused on that one since I don't know what do they mean "enter c000 and 10 into Start and Length" if I'm learning to program NES, as both console are same code yet different functionality, like

LDA #$01
STA $0230
LDA #$05
STA $0201
LDA #$08
STA $0202

These load color HEX code into selected Address, and that Address $200+ is the display of pixel from left to right then downward, then left to right. I don't think these code would work with NES because of different system. I Hope you understand what I mean.

EDIT:
PC is the program counter - it’s how the processor knows at what point in the program it currently is. It’s like the current line number of an executing script. In the JavaScript simulator the code is assembled starting at memory location $0600, so PC always starts there.
I have a feeling that I just learned that "PC" is actually "The active location of Address it's on right now."

User avatar
tokumaru
Posts: 11894
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Hello, I'm back, still need assistences

Post by tokumaru » Wed Jun 17, 2020 10:59 pm

Keep in mind that even though when programming we write words like "LDA", "JMP", "BCC", etc., the CPU itself doesn't know any of those words. It doesn't know how you're naming your variables either. When you assemble your code (using NESASM, ASM6, CA65 or any other assembler), the written program is converted into a series of bytes representing opcodes (operation codes) and operands (immediate values, addresses, or whatever the preceding opcode needs in order to do its job).

The job of an assembler is to scan your code and, based on the things you wrote, figure out which opcodes to use and how to encode the operands. For example, when an assembler finds the instruction JMP (Destination), it knows that "JMP" is an instruction with 2 addressing modes: absolute and indirect - the CPU can either jump to an address directly specified by the programmer, or it can get the destination address from RAM, at the location specified by the programmer. The assembler doesn't know which of these addressing modes the programmer intended to use just from looking at the word "JMP", it has to look at what comes next.

Then, it finds that the operand is enclosed in parenthesis (or square brackets, in the case of NESASM, which uses a different syntax for indirection), which means that this instruction is using indirect addressing (i.e. "Destination" is not the address you want to jump to, it's the address where the address you want to jump to it's stored - in other words, indirection). Looking at a reference document , you can see that the code that the CPU understands as "JMP indirect" is $6C, so the assembler outputs a byte with the value $6C to represent that operation. Then it needs to write the operand. It finds the word "Destination", which's a label created by the programmer at some point. The assembler then simply looks up what address that name is referring to and outputs that (e.g. $893B).

The entire instruction, after assembled, occupies 3 bytes in the output file: $6C, $3B, $89 (the address appears backwards because the lower byte is stored first). The CPU doesn't understand JMP (Destination), it understands $6C, $3B, $89. This is why we need assemblers: even though it's possible to write entire programs just by typing byte values directly, that's highly impractical (some people do it anyway!). We humans are generally better at remembering words than numbers, so most of us are more comfortable memorizing mnemonics such as "JMP" and "ADC", and naming the memory addresses we use, rather than using only numbers all the time.

And yes, the PC is the register that the CPU uses to read your code and execute it, so whatever it's pointing to, that's what the CPU is executing at that moment.

turboxray
Posts: 115
Joined: Thu Oct 31, 2019 12:56 am

Re: Hello, I'm back, still need assistences

Post by turboxray » Thu Jun 18, 2020 8:31 am

Garth wrote:
Wed Jun 17, 2020 1:58 pm
There's also absolute, indexed, indexed indirect, indirect indexed
Honestly, the documentation should read indexed->indirect, and indirect->indexed to show the order of the procedure more clearly IMO. I mean, it's the case of language; batman isn't a "bat" with human attributes (but the opposite) - yet English follows this pattern. In other languages, it would be "manbat". The order precedence arrow eliminates language bias.

I also dislike the usage of parenthesis method for indirection in almost all 65x assemblers. That's one thing NESASM gets right. Parenthesis should be for higher order compile time calculations, and [] for indirection. JMP (label+4).. is that going to be assembled as indirection? Hopefully the assembler is smart enough to know that's not indirection, but this is ; JMP ((label+4)). But that looks horrible, when you can just have JMP [label+4] which is explicitly clear.

Garth
Posts: 195
Joined: Wed Nov 30, 2016 4:45 pm
Location: Southern California
Contact:

Re: Hello, I'm back, still need assistences

Post by Garth » Thu Jun 18, 2020 10:53 am

turboxray wrote:
Thu Jun 18, 2020 8:31 am
I also dislike the usage of parenthesis method for indirection in almost all 65x assemblers. That's one thing NESASM gets right. Parenthesis should be for higher order compile time calculations, and [] for indirection. JMP (label+4).. is that going to be assembled as indirection?
The C32 assembler I use uses the curly braces for precedence in those few cases where it's needed. It would not be needed for JMP label+4. The 65816 assembly-language standard uses the [ ] to mean long indirect, ie, for 24-bit addressing rather than 16-bit.
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
tokumaru
Posts: 11894
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Hello, I'm back, still need assistences

Post by tokumaru » Thu Jun 18, 2020 1:00 pm

turboxray wrote:
Thu Jun 18, 2020 8:31 am
JMP (label+4).. is that going to be assembled as indirection?
It certainly is going to be assembled as indirection in every assembler I'm aware of (besides NESASM). Why would you use parenthesis in this case, though? You're not supposed to enclose an entire expression in parenthesis.

My real gripe with using parenthesis for indirection is that if you don't know that a specific instruction doesn't have an indirect mode, you may try to use it and the code will still assemble with the parenthesis being interpreted as precedence rather than indirection (e.g. JSR (SubroutinePointer), which will be silently assembled as JSR SubroutinePointer), resulting in bugs that are hard to catch.

DocWaluigean
Posts: 205
Joined: Sun Jun 17, 2018 6:41 pm

Re: Hello, I'm back, still need assistences

Post by DocWaluigean » Thu Jun 18, 2020 1:20 pm

tokumaru wrote:
Wed Jun 17, 2020 10:59 pm
Keep in mind that even though when programming we write words like "LDA", "JMP", "BCC", etc., the CPU itself doesn't know any of those words. It doesn't know how you're naming your variables either. When you assemble your code (using NESASM, ASM6, CA65 or any other assembler), the written program is converted into a series of bytes representing opcodes (operation codes) and operands (immediate values, addresses, or whatever the preceding opcode needs in order to do its job).

The job of an assembler is to scan your code and, based on the things you wrote, figure out which opcodes to use and how to encode the operands. For example, when an assembler finds the instruction JMP (Destination), it knows that "JMP" is an instruction with 2 addressing modes: absolute and indirect - the CPU can either jump to an address directly specified by the programmer, or it can get the destination address from RAM, at the location specified by the programmer. The assembler doesn't know which of these addressing modes the programmer intended to use just from looking at the word "JMP", it has to look at what comes next.

Then, it finds that the operand is enclosed in parenthesis (or square brackets, in the case of NESASM, which uses a different syntax for indirection), which means that this instruction is using indirect addressing (i.e. "Destination" is not the address you want to jump to, it's the address where the address you want to jump to it's stored - in other words, indirection). Looking at a reference document , you can see that the code that the CPU understands as "JMP indirect" is $6C, so the assembler outputs a byte with the value $6C to represent that operation. Then it needs to write the operand. It finds the word "Destination", which's a label created by the programmer at some point. The assembler then simply looks up what address that name is referring to and outputs that (e.g. $893B).

The entire instruction, after assembled, occupies 3 bytes in the output file: $6C, $3B, $89 (the address appears backwards because the lower byte is stored first). The CPU doesn't understand JMP (Destination), it understands $6C, $3B, $89. This is why we need assemblers: even though it's possible to write entire programs just by typing byte values directly, that's highly impractical (some people do it anyway!). We humans are generally better at remembering words than numbers, so most of us are more comfortable memorizing mnemonics such as "JMP" and "ADC", and naming the memory addresses we use, rather than using only numbers all the time.

And yes, the PC is the register that the CPU uses to read your code and execute it, so whatever it's pointing to, that's what the CPU is executing at that moment.
Keep in mind that even though when programming we write words like "LDA", "JMP", "BCC", etc., the CPU itself doesn't know any of those words. It doesn't know how you're naming your variables either. When you assemble your code (using NESASM, ASM6, CA65 or any other assembler), the written program is converted into a series of bytes representing opcodes (operation codes) and operands (immediate values, addresses, or whatever the preceding opcode needs in order to do its job).

I'll keep it in mind about how they convert codes with bytes.

The job of an assembler is to scan your code and, based on the things you wrote, figure out which opcodes to use and how to encode the operands. For example, when an assembler finds the instruction JMP (Destination), it knows that "JMP" is an instruction with 2 addressing modes: absolute and indirect - the CPU can either jump to an address directly specified by the programmer, or it can get the destination address from RAM, at the location specified by the programmer. The assembler doesn't know which of these addressing modes the programmer intended to use just from looking at the word "JMP", it has to look at what comes next.

I'm still confused about Absolute and Indirect. So "Absolute Jump" is by jumping directly to the address specified by programmer [Using Labels] and "Indirect Jump" is the same thing as Absolute, but instead of using Labels, it's using Address? That's what they're trying to explain?

Then, it finds that the operand is enclosed in parenthesis (or square brackets, in the case of NESASM, which uses a different syntax for indirection), which means that this instruction is using indirect addressing (i.e. "Destination" is not the address you want to jump to, it's the address where the address you want to jump to it's stored - in other words, indirection). Looking at a reference document , you can see that the code that the CPU understands as "JMP indirect" is $6C, so the assembler outputs a byte with the value $6C to represent that operation. Then it needs to write the operand. It finds the word "Destination", which's a label created by the programmer at some point. The assembler then simply looks up what address that name is referring to and outputs that (e.g. $893B).

I don't see the code about "JMP indirect" stuff?
JMP - Jump
Sets the program counter to the address specified by the operand.

Processor Status after use:

C Carry Flag Not affected
Z Zero Flag Not affected
I Interrupt Disable Not affected
D Decimal Mode Flag Not affected
B Break Command Not affected
V Overflow Flag Not affected
N Negative Flag Not affected
Addressing Mode
Opcode
Bytes
Cycles
Absolute
$4C
3
3
Indirect
$6C
3
5
NB:
An original 6502 has does not correctly fetch the target address if the indirect vector falls on a page boundary (e.g. $xxFF where xx is any value from $00 to $FF). In this case fetches the LSB from $xxFF as expected but takes the MSB from $xx00. This is fixed in some later chips like the 65SC02 so for compatibility always ensure the indirect vector is not at the end of the page.
Okay, I don't know Absolute and Indirect at this time, since it made more sense to use JMP more without the Absolute and Indirect knowledge.

The entire instruction, after assembled, occupies 3 bytes in the output file: $6C, $3B, $89 (the address appears backwards because the lower byte is stored first). The CPU doesn't understand JMP (Destination), it understands $6C, $3B, $89. This is why we need assemblers: even though it's possible to write entire programs just by typing byte values directly, that's highly impractical (some people do it anyway!). We humans are generally better at remembering words than numbers, so most of us are more comfortable memorizing mnemonics such as "JMP" and "ADC", and naming the memory addresses we use, rather than using only numbers all the time.

I don't think I understand about certain part about 3 bytes in the output file. and stuff. When you said 3 bytes in output file, you mean A, X, and Y Registers, since A = 6C, X = 3B, and Y = 89? It's true that we're better at remembering words than numbers since the numbers goes infinite, even through the number of Pi.

User avatar
tokumaru
Posts: 11894
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Hello, I'm back, still need assistences

Post by tokumaru » Thu Jun 18, 2020 2:35 pm

DocWaluigean wrote:
Thu Jun 18, 2020 1:20 pm
I'm still confused about Absolute and Indirect. So "Absolute Jump" is by jumping directly to the address specified by programmer [Using Labels] and "Indirect Jump" is the same thing as Absolute, but instead of using Labels, it's using Address? That's what they're trying to explain?
No. Indirect is when the operand isn't actually the thing the operator needs, it's actually the address of the thing the operator needs. Back to our analogy of opening a door: indirection would be if instead of being given the key to the door, you were given a piece of paper indicating where the key is - in order to open the door you'd first have to go and get the key at the specified location, and then use it in the door to complete the instruction.

The CPU only understands addresses, it doesn't know anything about labels. Labels are just nicknames for addresses, a convenience provided by the assembler to help us keep track of where things are in memory.
I don't see the code about "JMP indirect" stuff?
Here:
Indirect
$6C
There's a table of addressing modes for each instruction, where it shows the opcode, the number of bytes occupied by the assembled instruction, and the number of cycles it takes to execute.
Okay, I don't know Absolute and Indirect at this time, since it made more sense to use JMP more without the Absolute and Indirect knowledge.
Then don't use indirect jumps for now. Just be aware that there are different ways to provide the operators with the operands they need, and for that there are different addressing modes.
I don't think I understand about certain part about 3 bytes in the output file. and stuff. When you said 3 bytes in output file, you mean A, X, and Y Registers, since A = 6C, X = 3B, and Y = 89?
Absolutely not. What I meant is that the CPU can't interpret text, it can only interpret numbers in the form of bytes, so we need assemblers to convert the programs we write in text form into the sequences of bytes that the CPU will understand. The command JMP Address becomes 3 bytes because the first byte is the opcode (operation code), which tells the CPU what it has to do, which in this case is jump to a specific address. And the other 2 bytes are the operand, the thing that the CPU needs in order to carry out this operation, which in this case is the address where it must jump to. Addresses are 16-bit values, so you need to bytes in order to represent an address.

DocWaluigean
Posts: 205
Joined: Sun Jun 17, 2018 6:41 pm

Re: Hello, I'm back, still need assistences

Post by DocWaluigean » Thu Jun 18, 2020 11:43 pm

tokumaru wrote:
Thu Jun 18, 2020 2:35 pm
DocWaluigean wrote:
Thu Jun 18, 2020 1:20 pm
I'm still confused about Absolute and Indirect. So "Absolute Jump" is by jumping directly to the address specified by programmer [Using Labels] and "Indirect Jump" is the same thing as Absolute, but instead of using Labels, it's using Address? That's what they're trying to explain?
No. Indirect is when the operand isn't actually the thing the operator needs, it's actually the address of the thing the operator needs. Back to our analogy of opening a door: indirection would be if instead of being given the key to the door, you were given a piece of paper indicating where the key is - in order to open the door you'd first have to go and get the key at the specified location, and then use it in the door to complete the instruction.

The CPU only understands addresses, it doesn't know anything about labels. Labels are just nicknames for addresses, a convenience provided by the assembler to help us keep track of where things are in memory.
I don't see the code about "JMP indirect" stuff?
Here:
Indirect
$6C
There's a table of addressing modes for each instruction, where it shows the opcode, the number of bytes occupied by the assembled instruction, and the number of cycles it takes to execute.
Okay, I don't know Absolute and Indirect at this time, since it made more sense to use JMP more without the Absolute and Indirect knowledge.
Then don't use indirect jumps for now. Just be aware that there are different ways to provide the operators with the operands they need, and for that there are different addressing modes.
I don't think I understand about certain part about 3 bytes in the output file. and stuff. When you said 3 bytes in output file, you mean A, X, and Y Registers, since A = 6C, X = 3B, and Y = 89?
Absolutely not. What I meant is that the CPU can't interpret text, it can only interpret numbers in the form of bytes, so we need assemblers to convert the programs we write in text form into the sequences of bytes that the CPU will understand. The command JMP Address becomes 3 bytes because the first byte is the opcode (operation code), which tells the CPU what it has to do, which in this case is jump to a specific address. And the other 2 bytes are the operand, the thing that the CPU needs in order to carry out this operation, which in this case is the address where it must jump to. Addresses are 16-bit values, so you need to bytes in order to represent an address.
So labels is NESDEV exclusive 6502 program created for community-made ASM of NES?
it's actually the address of the thing the operator needs. Back to our analogy of opening a door: indirection would be if instead of being given the key to the door, you were given a piece of paper indicating where the key is - in order to open the door you'd first have to go and get the key at the specified location, and then use it in the door to complete the instruction.
I almost understand this, but I keep losing words to describe it easily for me. Indirect Jump has to do with BNE and BEQ since they need the Flag to set to 1 or 0 for it? And Absolute Jump has to do with using JMP simply?

Ah, I see.

Although it's better for me to understand about Indirection it now than later..since I might forget it exist.

That somewhat makes sense to me about it. CPU only understands numbers and 1 and 0. And possibly, the Opcode/instructions is the first byte, and 2nd + 3rd byte represent the $XF [or $FFXX] and $FX [or $XXFF like high byte and low byte?] . I thought NES is 8-bit values as it only goes up to 255.

Garth
Posts: 195
Joined: Wed Nov 30, 2016 4:45 pm
Location: Southern California
Contact:

Re: Hello, I'm back, still need assistences

Post by Garth » Fri Jun 19, 2020 12:29 am

DocWaluigean wrote:
Thu Jun 18, 2020 11:43 pm
So labels is NESDEV exclusive 6502 program created for community-made ASM of NES?
Labels are used by all assemblers. Labels just give names that are meaningful to humans, to various places in memory, whether variables, tables, code, whatever.

I almost understand this, but I keep losing words to describe it easily for me. Indirect Jump has to do with BNE and BEQ since they need the Flag to set to 1 or 0 for it? And Absolute Jump has to do with using JMP simply?
No; BNE and BEQ (and friends) are branches that are conditional in their execution, and relative. "Relative" means the instruction's operand tells the instruction how far and in which direction to jump. It adds the signed jump distance to the address of the next instruction, whatever that is; so if the operand is $10, $410+$10 is $420; and $B731+$10 is $B741. The fact that it's a relative offset of $10 makes it skip forward that amount regardless of what address the branch instruction is at.

The JMP instruction OTOH is never relative or conditional. If it's absolute, it's telling the processor, "Go to the exact address I'm telling you." But if it's indirect, it's telling it, "Read this other address first to find out where you're supposed to ultimately jump to." IOW, indirect gives the address of an address.

That somewhat makes sense to me about it. CPU only understands numbers and 1 and 0. And possibly, the Opcode/instructions is the first byte, and 2nd + 3rd byte represent the $XF [or $FFXX] and $FX [or $XXFF like high byte and low byte?] . I thought NES is 8-bit values as it only goes up to 255.
Instructions always have an op code, but many also have an operand, bringing the total to two or three bytes. The op code plus operand together are the instruction. The data bus is only 8 bits wide, so there are only 256 combinations of bits that it can transfer at once. The address bus however is 16 bits wide, so there are 65,536 possible combinations, ie, addresses. Since we often have to communicate an address, it takes two 8-bit bytes to get it through. (You can also do math with 16 bits, 24 bits, 32 bits, or more, by breaking it down for the processor to handle 8 bits at a time.)
http://WilsonMinesCo.com/ lots of 6502 resources

Garth
Posts: 195
Joined: Wed Nov 30, 2016 4:45 pm
Location: Southern California
Contact:

Re: Hello, I'm back, still need assistences

Post by Garth » Mon Sep 14, 2020 5:05 pm

Any progress?
http://WilsonMinesCo.com/ lots of 6502 resources

Post Reply