How does the 6502's machine code process $ vs #$, as in it's assembly language? Does every piece of machine code have an extra byte or something telling to use addresses or values or was it something more clever? (finding info on 6502 assembly is easy, on machine code processing in general not so much, so I don't know if there's a standard way or if this is a stupid question or not!)
-
Welcome to Retrocomputing. Thanks for the question; if there are no answers later I might answer it. Do you want to know about the 6502 bytecode (i.e. programs) or the hardware implementation as well?– wizzwizz4 ♦Commented Jan 26, 2017 at 7:08
-
I want to personally endorse the superb forum for 6502. Those guys know everything there is to know about the 6502/65C02/65816, etc. forum.6502.org– cbmeeksCommented Jan 26, 2017 at 21:42
-
1Actually, complete listings of all the 6502 machine language opcodes in raw hexadecimal are easy to find. Examples: visual6502.org/wiki/index.php?title=6502_all_256_Opcodes , llx.com/~nparker/a2/opcodes.html , 6502.org/tutorials/6502opcodes.html , oxyron.de/html/opcodes02.html , etc.– hotpaw2Commented Jul 18, 2017 at 22:30
3 Answers
While @dirkt's is a good answer, I think it might be missing the high-level overview you're after.
On the most basic level, instructions using immediate vs absolute addressing are encoded into different opcodes. For example, LDA # (immediate mode) is encoded as A9 (after which the CPU knows, by mechanisms detailed in @dirkt's answer, to read one byte and interpret it as a value), whereas LDA (absolute mode) is encoded as AD (and the CPU knows to read two bytes and interpret it as an address).
-
2I agree that this answer probably is what the OP was looking for although @dirkt's answer explains how this is possible without resorting to extra opcode bytes. Look at an opcode table to see how the various opcodes are defined: oxyron.de/html/opcodes02.html Commented Jan 26, 2017 at 12:15
How does the 6502's machine code process $ vs #$, as in it's assembly language? Does every piece of machine code have an extra byte or something telling to use addresses or values or was it something more clever?
Just to expand a bit on Muzer's answer...
All 6502 opcodes use exactly one byte, no exceptions. In this one byte, is encoded both what the operation is (load, store, add, rotate etc) and what the address mode is. The address mode is what tells the processor where to get the operand. For example in LDA #10
is immediate - the operand follows the opcode. With LDA $10
the address mode can be either absolute (the operand is in the location specified by the two bytes following the opcode) or zero page which is the same as absolute except that, because you know the highest byte of the address is 0, it can be specified by the one byte following the opcode.
The address mode is specified by some of the bits in the opcode. For LDA we have the following bit patterns:
LDA zp, x indirect 0xA1 10100001
LDA zero page 0xA5 10100101
LDA immediate 0xA9 10101001
LDA absolute 0xAD 10101101
LDA zp ind, y 0xB1 10110001
LDA zp, x 0xB5 10110101
LDA abs, y 0xB9 10111001
LDA abs, x 0xBD 10111101
If you focus on bits 2, 3 and 4, you can see that these three bits are the only difference for each of the above instructions and they specify the address mode for LDA
. The other bits specify "LDA" i.e. 101xxx01
means LDA
.
Eight of the instructions follow that pattern, for example 000xxx01
is for ORA
, 001xxx01
is for AND
, 100xxx01
is for STA
except that 10001001
does not mean STA immediate for obvious reasons.
The principle sort of holds for some of the other instructions too. e.g. LDX
, LDY
but usually not all the address modes make sense for these or there is a deliberate choice not to have them. e.g. CPX
does not have a full set of address modes. The gaps are used for other things e.g. INX
is in the place where you would expect CPX #xx
.
The 6502 has been decapped and traced, and a simulator is available, so you can find out the workings of anything in as much detail as you want.
The block diagram (available even before the decap) helps a lot in understanding what is going on.
Generally, instructions were executed in several phases (T0-T5), and the instruction register and the current phases were decoded first with a ROM, and then with a PLA into signals which drive the various parts of the CPU, including the next phase. The state machine wiki page has some of the more intricate details.
So for immediate vs. absolute addressing, the state machine sequences would slightly differ: Immediate would fetch the byte after the opcode (actually this was pipelined, and happened always at the same time as opcode decoding, which is why each opcode takes at least 2 cycles), and then this value would be routed to the ALU. Absolute addressing would fetch two bytes after the opcode, route them to the address bus latches, use them to fetch the byte at this address, and route that to the ALU.
The simulator allows you to enter your own programs, so just enter both variantes and see what happens.