A simple web-based 6502 emulator is available at http://6502.cdot.systems (note that this is an http link, not an https link). This emulator is used in the SPO600 course to teach 8-bit assembly language before transitioning to more complex 64-bit x86_64 and AArch64 assembly language.
In most 6502 documentation, including this page, the $
prefix indicates hexadecimal notation. (Note that in some other contexts, hexadecimal is indicated by a 0x
prefix or an h
suffix).
The emulator has a text area for entering and editing code, a small bit-mapped graphics screen (32×32 pixels), a character screen (80×25 characters), a debug area, a memory monitor, and a message area.
These controls are available at the top of the screen:
The Speed slider lets you adjust the speed of the emulator from about 1% of native 6502 performance (left) to roughly full native speed of a 1MHz CPU (right; this is not fully accurate to the CPU speed since the emulator is not cycle-accurate). Setting the speed slider to a lower setting can be useful for debugging and for viewing the progress of operations on the displays.
There are also controls to Save and Load the text area to/from local storage on the computer on which it is running (as a download/upload); this works nicely with a local git repository (or clone).
The assembler accepts these inputs:
STA $10
LOOP: STA ($10),Y
JMP LOOP
*=$XXXX
where XXXX is an address in hexadecimal. Multiple origin assignments may be used. Example: *=$1800
define macro value
– for example: define WHITE $01
– the macro value will be substituted into lines wherever the macro name appears (e.g., LDA #WHITE
).LDA #<START
- note that this only works with labels, and not with macros.*=$f000 DISPLAY:
You could then create a pointer to that address at $0027 with this code:
LDA #<DISPLAY STA $27 LDA #>DISPLAY STA $28
;
are treated as a comment and ignored.The debugger will constantly show the value of the emulated 6502's registers. If you select the Debugger checkbox, you will be able to single-step through memory or jump to an address or label using the associated pushbuttons.
Selecting the Monitor checkbox will display the specified region of memory as code is executed. For example, specifying a start of $00 and a length of $100 will display the entire zero page. The monitor display is updated with after each execution of one (or more) instructions.
The checkbox labeled “Text Screen” can be used to hide the character display to free up more screen space for editing code. Note also that the character display can be used for additional program memory (whether the display is enabled or not) when it's not required for output.
The entire 64K address space is available and is populated with RAM except for peripherals and a small ROM area.
The memory map contains these regions:
There are four peripherals available:
The Reset button clears the zero page, bitmap display, and character display, and resets the stack pointer (SP=$ff), program counter (PC=$0600), status register (P=$30), and the general purpose registers (A=X=Y=$00).
Code is assembled starting at $0600 (unless the code changes the location with a *=address
directive). Memory following the program is reset to $00. A BRK
instruction ($00) will cause the program to stop and return control to the debugger.
For more details, press the Notes button in the emulator.
Many 6502 personal/home computers had the operating system installed in read-only memory (ROM) chips. The emulator has a small ROM chip with these simple input/output (I/O) routines defined:
If C=0: X,Y registers set the cursor position Y:A is returned as a pointer to the current screen position (i.e., Y is the high byte and A is the low byte of a pointer to the memory address of the current cursor position) If C=1: X,Y registers return the current cursor position A contains the character at the current cursor location
Registers which are not used for input/output are not affected by the ROM routines. The ROM routines use $f0-fd in the zero page for variable storage.
To use the ROM routines, these define directives may be pasted into your code:
define SCINIT $ff81 ; initialize/clear screen define CHRIN $ffcf ; input character from keyboard define CHROUT $ffd2 ; output character to screen define SCREEN $ffed ; get screen size define PLOT $fff0 ; get/set cursor coordinates
You can then access the routines by name using the JSR
instruction:
LDA #$41 ; ASCII code for the letter "A" JSR CHROUT ; execute the CHROUT routine (print the character on the screen)
The ROM routine names and locations pay homage to a famous 6502-based family of computers. Discovering which one is left as an exercise for the reader!
See the 6502 Emulator Example Code page.
The emulator's source code can be found at https://github.com/ctyler/6502js … Pull Requests are welcome.