Page 1 of 2
Program Counter initialization
Posted: Thu Dec 09, 2010 3:44 pm
by Mindiell
Hi there,
I'm completely new to the 6502 world, and I'm coding an emulator for this microprocessor. I already read a lot of things on it, but I get stuck with one little thing at this moment :
- How the processor know where to start the Program Counter ?
I saw some sources with .ORG 4000 or .ORG 0801, but does this command put something like "push 4000 in PC" at address 0 (where PC is initialized for example) ?
I saw other sources in SREC format like this one :
Code: Select all
S1234000D8182022403820224000414F4B62696E61727900F8182022403820224000414F34
S12340204B0008A90085A085A128082077400885A26885A32808206C400885A4C5A2D014F7
S12340406885A5C5A3F01B00466661696C20666C6167730000466661696C20726573756C1B
S12340607400E6A0D0C3E6A1D0BF2860A5A149FF85A6A5A0E5A660A5A065A160A90085A3AC
S1114080A5A065A10885A29002E6A3286060B1
How can the processor could guess where to start ? Or, by loading this file, it put the PC to the first address encountered (0x4000 here) ?
Hoping this is not a too much stupid question...
Posted: Thu Dec 09, 2010 5:03 pm
by 8BIT
welcome!
That is a good question. On reset, the processor will read address $FFFC and $FFFD (called the reset vector) and load the program counter (PC) with their content.
For example, if $FFFC = $00 and $FFFD = $10, then the PC will get loaded with $1000 and execution will start there. However, most 6502 systems contain ROM in the upper address region, say $E000-$FFFF so it's likely that the reset vector will point to a location there.
Most systems have an OS of some sorts - ranging from a simple machine language monitor, BASIC interpreter, even GUI interfaces such as Contiki.
Your OS must have a method of loading the programs generated from an assembler or compiler into RAM. It must also have a method of executing code in RAM.
For simplicity, lets say you have a simple command line promt and you can load a program using the "LOAD Example.obj, $1000" command.
This will load the program named Example.obj into RAM at address $1000.
Next, from the command prompt, you would type "Exec $1000" which would move the address $1000 into the PC register and begin executing your program.
You must have some sort of OS capable of doing these two steps in order to load and execute programs.
I hope that helps!
Daryl
Posted: Thu Dec 09, 2010 8:02 pm
by GARTHWILSON
The ".ORG" is a directive for the assembler, telling the assembler what to do, not the target processor. .ORG 4000 tells the assembler to start laying down code at the address 4000. It does not mean the processor will start there unless you make your reset vector (in address FFFC-FFFD) point there. You can have more than one occurrence of .ORG in your code. At a minimum, you will usually have one to start the code, and, at the end, a .ORG FFFA to start laying down your three vectors.
Posted: Thu Dec 09, 2010 9:24 pm
by Mindiell
Thank you,
So, if I understand well, the processor will, at start and at each reset, set the PC register to what it found in the reset vector ($FFFC-$FFFD) ?
Actually, what I want to do is doing Atari2600 emulation and I'm trying to emulate (or simulate I think) the 6502. So, right now I want to test some codes in order to verify that my simulator is doing well. So I'm loading some small asm programs in is memory. But since I'm initializing everything at 0, the PC is at 0 at the start. I think I will change that in order to set the PC to the first address found in the loading procedure.
D'ont know if this is the best, but it's just for testing right now, I'll change this later.
By the way, I saw the P register being initialized at $20. Why the useless bit is set ? Why isn't it clear ? (I saw this in a thread and in an other simulator)
Thank you again,
Posted: Thu Dec 09, 2010 10:23 pm
by GARTHWILSON
So, if I understand well, the processor will, at start and at each reset, set the PC register to what it found in the reset vector ($FFFC-$FFFD) ?
Right. The reset vector is read during the reset sequence.
Right again. If it's software only, it's a simulator.
But since I'm initializing everything at 0, the PC is at 0 at the start. I think I will change that in order to set the PC to the first address found in the loading procedure.
We recently discussed this somewhere else, but it will take me awhile to think of what to search for to find it. The reset is a type of interrupt, and at least some of the 6502 variations (all 65c02, I think) start the reset sequence with stacking the current PC, so theoretically you could use that in a crash recovery to find out where it was. After stacking the PC, it loads it with the reset vector.
By the way, I saw the P register being initialized at $20. Why the useless bit is set ? Why isn't it clear ?
I don't know, but at least add 04 to that. It should come up with the interrupt-disable bit set.
Posted: Thu Dec 09, 2010 11:24 pm
by kc5tja
Unused bits are typically set because of internal pull-up resistors (or their MOS equivalents). These enforce a known-good logic level on unused signal lines, so that gates don't go into latch-up, draw excessive power, etc.
The choice of a logic-high versus logic-low is usually conventional in nature, and probably depends on which power rail is closest in the chip.
Posted: Fri Dec 10, 2010 2:59 am
by BigDumbDinosaur
By the way, I saw the P register being initialized at $20. Why the useless bit is set ? Why isn't it clear ?
I don't know, but at least add 04 to that. It should come up with the interrupt-disable bit set.
$20 represents the unused status register bit in the 65(c)xx, which is always set. In the 65C816, that bit is used to set the width of memory and accummulator operations.
Code: Select all
65(c)xx Status Register
-----------------------
xx0xxxxx
|| |||||
|| ||||+---> 1 = arithmetic carry
|| |||+----> 1 = arithmetic zero
|| ||+-----> 0 = interrupt request enabled
|| || 1 = interrupt request disabled
|| |+------> 0 = binary mode enable
|| | 1 = decimal mode enabled
|| +-------> 1 = forced break detected
|+---------> 1 = arithmetic sign overflow
+----------> 1 = arithmetic negative
65C816 Status Register (native mode)
------------------------------------
xxxxxxxx
||||||||
|||||||+---> 1 = arithmetic carry
||||||+----> 1 = arithmetic zero
|||||+-----> 0 = interrupt request enabled
||||| 1 = interrupt request disabled
||||+------> 0 = binary mode enable
|||| 1 = decimal mode enabled
|||+-------> 0 = 16 bit index registers
||| 1 = 8 bit index registers
||+--------> 0 = 16 bit accummulator
|| 1 = 8 bit accummulator
|+---------> 1 = arithmetic sign overflow
+----------> 1 = arithmetic negative
BRK does not require differentiation in the 65C816 because it has its own vector. Also note that the BRK bit is meaningless unless a BRK opcode was actually executed, in which case the MPU will push the status register onto the stack with bit 5 set. An IRQ will do the same but with bit 5 clear, which is how you tell if an interrupt request was hardware or software:
Code: Select all
tsx ;get stack pointer
lda $0101,X ;get copy of status register
and #%00100000 ;check if BRK bit is set
bne goto_brk_handler
beq goto_irq_handler
Posted: Fri Dec 10, 2010 8:40 am
by Mindiell
Great ! I was certain there was a hardware explanation and kc5tja explained very well.
Thanks for all this information. I'll try to do my best now.
Oh, and as I'm here, a last question

Do you know where I can find a 6502 compiler with which I can take a source and obtain the binary result ?
I had a look at the Michal Kowalski which is great for test my own simulator, as I can compile a source code and test the result, but I can't grab the binary in order to use it in my own simulator : I don't want to do a compiler, just a simulator
EDIT :
By the way, after verification. When compilig and debugging a simple code source like this :
Code: Select all
.ORG $4000
start:
; EXPECTED FINAL RESULTS: $0210 = FF
; (any other number will be the
; test that failed)
; initialize:
LDA #$00
STA $0210
; store each test's expected
LDA #$55
STA $0200
LDA #$AA
STA $0201
LDA #$FF
STA $0202
LDA #$6E
STA $0203
LDA #$42
STA $0204
LDA #$33
STA $0205
LDA #$9D
STA $0206
LDA #$7F
STA $0207
LDA #$A5
STA $0208
LDA #$1F
STA $0209
LDA #$CE
STA $020A
LDA #$29
STA $020B
LDA #$42
STA $020C
LDA #$6C
STA $020D
LDA #$42
STA $020E
This simulator (the one by Michal Kowalski) is initializing everything to a 0 value apart :
- the Processor Status : $20 no problem
- the Stack Pointer : $FF ok, this is the top of the stack
- the Program Counter : $4000, strange, because all vectors are empty (from $FFFA to $FFFF)
So, I guess loading the binary inside this simulator tends to use the first ORG to initialize the PC...
EDIT 2 :
I found this in the programmingmanual.pdf :
The code generated by the assembler, when linked, will begin at the default origin location, $2000.
Is it possible to verify this default value by using a real hardware processorand just read the PC value without programming anything ? (maybe reading on some pin I guess... But I'm not an electronic scientist, just a poor computer developer)
Posted: Fri Dec 10, 2010 10:38 am
by GARTHWILSON
Oh, and as I'm here, a last question
Ask as many as you wish. There are no limits (except when we can see someone asks without putting out any effort, as happened recently).
Do you know where I can find a 6502 compiler with which I can take a source and obtain the binary result ?
It sounds like you just want an assembler. Almost any assembler should work. Most have several options for output format.
- the Stack Pointer : $FF ok, this is the top of the stack
You should normally initialize this in your reset routine. The most common sequence is LDX#FF, TXS.
I found this in the programmingmanual.pdf :
The code generated by the assembler, when linked, will begin at the default origin location, $2000.
Is it possible to verify this default value by using a real hardware processor and just read the PC value without programming anything ?
The processor absolutely will not automatically start at $2000 or $4000 or anything predictable without loading the vector into the PC. The
assembler might have an implied .ORG $2000, but the assembler is not the processor. The only sensible and normal way to start the processor will be with a reset which will make the processor start at the address the reset vector points to.
Your code says, "; EXPECTED FINAL RESULTS: $0210 = FF"; but the only value written to $0210 is 0, so that's what will be there at the end. A better way to write those numbers to memory might be with a loop and a table though, and start at the end and go backwards for the easiest and most-efficient indexing:
Code: Select all
TABLE: DFB $55, $AA, $FF, $6E, $42, $33, $9D, $7F, $A5, $1F, $CE, $29, $42, $6C, $42
INIT: STZ $210
LDX #$0E
LOOP: LDA TABLE,X
STA $200,X
DEX
BPL LOOP
I normally use the assembler directive "RADIX HEX" also so I don't have to keep writing the "$".
Posted: Fri Dec 10, 2010 1:36 pm
by Mindiell
Ask as many as you wish. There are no limits (except when we can see someone asks without putting out any effort, as happened recently).
Thank you so much, but next time I'll do another thread in order to make it easier for someone else looking for the same information
It sounds like you just want an assembler. Almost any assembler should work. Most have several options for output format.
Great, I had a look in your
Development Tools: Assemblers and Disassemblers and the link to TASM is bad : it's linked to the fasm archive but the tasm archive is existing. I don't know who can change this link
Well, not a code from me, just a soure I used to see how the emulator was working. Thus, thanks for the tip about the table thing. It could be usefull.
Posted: Fri Dec 10, 2010 1:39 pm
by BitWise
My portable assembler can produce a binary files (and hex and S19).
http://www.obelisk.demon.co.uk/dev65/
Posted: Fri Dec 10, 2010 1:44 pm
by Mindiell
Thanks again,
I don't use java right now, but I downloaded the AS65 assembler from "Frank".
By the way, this time I know who to ask to change the link, the AS65 link is broken, and the correct link is :
http://www.obelisk.demon.co.uk/6502/as65_111.zip

Posted: Fri Dec 10, 2010 6:06 pm
by leeeeee
I had a look at the Michal Kowalski which is great for test my own simulator, as I can compile a source code and test the result, but I can't grab the binary in order to use it in my own simulator
After assembling go to the File -> Save code... menu or press [CTRL]K to bring up the save code dialog.
-the Program Counter : $4000, strange, because all vectors are empty (from $FFFA to $FFFF)
The reset vector will be used if you hit the RST icon or press [CTRL][SHIFT]R otherwise the first .ORG value will be used.
Lee.
Posted: Fri Dec 10, 2010 6:13 pm
by BigDumbDinosaur
Do you know where I can find a 6502 compiler with which I can take a source and obtain the binary result ?
Not to be pedantic about it, but you
assemble 65xx machine code, not compile. A compiler translates a higher level language (e.g., C or COBOL) to machine language, usually by first generating an assembly language source file and then assembling the assembly language instructions. Compilers confer a degree of portability between systems (e.g., a program written in C is usually portable between systems for which a native C compiler exists) and insulate the programmer from the raw machine code instruction set of the target system. By definition, assembly language is not portable, as each MPU has its own instruction set and each system has its own unique architecture.
I had a look at the Michal Kowalski which is great for test my own simulator, as I can compile a source code and test the result, but I can't grab the binary in order to use it in my own simulator : I don't want to do a compiler, just a simulator

You'd be better off, in my opinion, developing your own simulator from scratch. The Kowalski simulator is a fine piece of software, but deviates from 65xx assembler standards in several ways and also does not correctly implement all features of the NMOS version of the 6502 family (e.g., incorrect handling of .Z when in BCD mode). Also, I have never been able to get the I/O window features to work in it.
I found this in the programmingmanual.pdf :
The code generated by the assembler, when linked, will begin at the default origin location, $2000.
Is it possible to verify this default value by using a real hardware processorand just read the PC value without programming anything ? (maybe reading on some pin I guess... But I'm not an electronic scientist, just a poor computer developer)
Start your source code with .ORG <address> or *=<address> to set the starting assembly address. There is seldom a default and the MPU itself goes to $FFFC-$FFFD for the starting address following a hard reset.
Posted: Sun Dec 12, 2010 8:02 pm
by Mindiell
leeeeee : Thank you, I'll have a look at it.
BigDumbDinosaur : GARTHWILSON did correct me, but thanks again for helping me being more precise. Thanks for the help about the starting address.
As I said I want to do a simulator for the Atari 2600 and I'm starting by simulating the 6502. And whithout the informations about the 2600 I sometimes get stuck. By the way, it seems that the 6502 is never used alone and has a minimal OS to set some default like this starting address.
Thanks again everyone !