Best way to learn 6502 assembly without real hardware?

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
Lazy1
Posts: 9
Joined: 14 Jul 2004

Best way to learn 6502 assembly without real hardware?

Post by Lazy1 »

Is it possible to learn 6502 assembly on my pc?
I have several apple IIs lying around but the keyboards are not friendly when it comes to lots of typing - that and the small screen size.
After learning how to program for the 6502 I'd like to build a small computer, what can you recommend for someone who knows a bit about electronics but nowhere near enough to build something useful?

Thanks.

[Edit]
Oops, forgot to look on the tools page...
I found a simulator but what about building 6502 based computers?
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Re: Best way to learn 6502 assembly without real hardware?

Post by kc5tja »

Lazy1 wrote:
Oops, forgot to look on the tools page...
I found a simulator but what about building 6502 based computers?
The best way to learn how to build a 6502 based computer is to first learn these two things:

* Basic digital electronics

* Digital electronics timing analysis (which is the key to learning more advanced digital electronics stuff anyway)

Once you learn those two things, then you're ready to basically just dive right in. There is no right or wrong way to build a 6502-based computer.

You're free to look at my Kestrel project as an idea generator, although I used the 65816 processor because I wasn't forced to place RAM in the low addresses like the 6502 forces. Which should be a good idea for you to look at anyway, because a very handy skill to learn is how to generalize concepts off of reading other people's schematics. :-)

http://www.falvotech.com/projects/kestrel/1p3.php
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

Thanks for the info, any specific books/sites you can recommend?
Still learning 6502 asm, the site I looked at didn't explain the code samples very well but I picked up enough to do this:

Code: Select all

	.ORG $200
Hello:	.ASCII "Hello!", $00
	.START .Main

.Main	LDY #$00	; String indexer
.getch	LDX Hello, Y	; TODO: String address
	BNE .prtch	; If this is a valid character print it to the screen
	BEQ .fin	; Null terminator? End this now
	
.prtch	TXA		; Transfer X to the accumulator
	STA $E001	; Write the character stored in the accumulator to the screen
	INY		; Point to the next character
	JMP .getch	; Grab the next character
.fin	BRK		; Ends execution?
Anything completely wrong in there?
Thanks for the help so far.
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

Lazy1 wrote:

Code: Select all

	.ORG $200
Hello:	.ASCII "Hello!", $00
	.START .Main

.Main	LDY #$00	; String indexer
.getch	LDX Hello, Y	; TODO: String address
	BNE .prtch	; If this is a valid character print it to the screen
	BEQ .fin	; Null terminator? End this now
	
.prtch	TXA		; Transfer X to the accumulator
	STA $E001	; Write the character stored in the accumulator to the screen
	INY		; Point to the next character
	JMP .getch	; Grab the next character
.fin	BRK		; Ends execution?
Anything completely wrong in there?
Thanks for the help so far.
Nothing is inherently wrong with the code, except that it wastes some amount of time using registers that it doesn't need to use. I would write the above like this instead:

Code: Select all

	.ORG $200
Hello:	.ASCII "Hello!", $00
	.START .Main

.Main	LDY #$00	; String indexer
.getch	LDA Hello, Y	; TODO: String address
	BEQ .fin	; Null terminator? End this now.  Otherwise . . .
	
.prtch	STA $E001    ; Write the character to the screen
	INY		; Point to the next character
	JMP .getch	; Grab the next character
.fin	BRK		; Ends execution by invoking the system debugger.
Notice that I did away completely with using the X register, because loading the A register sets the CPU's flags properly too. Also, I eliminated the BNE instruction because, logically, if BEQ didn't work, it must be non-equal, and so we "fall through" into the .prtch routine. A already holds the character to print, so we just store it in the output register (I'm assuming this is some kind of simulator parallel port?).
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

Thanks for the tip, and yes, writing to $E001 in the simulator outputs a character to a display window.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Post by GARTHWILSON »

> I have several apple IIs lying around but the keyboards are not
> friendly when it comes to lots of typing - that and the small screen size.

Have the keyboards gone bad? When you get more advanced, you'll want to be able to use a full-featured text editor and a nice macro assembler; but those are not at all necessary just to start. Some of us started on the AIM-65 which, although it had a querty keyboard, only had a one-line, 20- or 24-character display, and a little printer built in that resembled a supermarket receipt printer.

There are a lot of resources on this website, and a lot more on the way (even if they are slow in coming).
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

The keyboards aren't broken, they just have the keys too close together.
The other thing is my only apple II assembly book gives you a broken assembler to work with and the code in the book uses commands only their assembler understands.

I'm still looking for more tutorials though, the one I found was pretty brief and didn't cover things like interrupts or the stack.
I'll keep looking.
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

I have been reading through my 6502 book and some examples required display memory to write to inorder to change the screen.
Since the simulator I'm using does not have any display memory I decided to emulate it starting at $200 until $3B8 which should fill the simulator display console.
I'm surprised it actually worked but there is a bug when I try and copy from the other vram page.
Like, I load the display base address's high byte into the accumulator ( $02 ) and then I add 1 to it inorder to point to the next page.
For clearing the screen this works, when writing the screen contents to the simulator's console output address ADC produces $04 in the accumulator instead of $03 which it does in the screen clear code.

Sorry if the code is ugly and it will be hacked together as I haven't gotten that far into the book.

Code: Select all

		.ORG $00
DisplayWidth:	.DB $28
DisplayHeight:	.DB $0B
DisplayBaseAddr:.DW $200
DisplayEndAddr:	.DW $3B8
DisplaySize:	.DW $1B8
DisplayPos:	.DW $00		; Counter for screen display ( 16 bits )
Test:		.ASCII "This is a very long string used to test the emulated display memory, will it work? Who knows....", $00
		.START Main
		
; Linear display memory emulator
; Emulated video memory starts at $200 and extends to $3B8
	
; HACKHACKHACK
; Testing purposes only
Main	JSR EmuDisplayClear
	LDY #$00
.NextCh	LDA Test, Y
	STA (DisplayBaseAddr), Y
	BEQ .Fin
	INY
	JMP .NextCh
.Fin
	LDA #$41
	STA $305
	NOP
	NOP
	JSR EmuDisplayCopy
	BRK
	
; Clears out the emulated video memory
; ======================================
EmuDisplayClear						; Clear the first page of VRAM
			LDA #$00			; Load 0 into the accumulator
			LDY #$00			; Load 0 into the Y register

.ClearWriteToVRAM1	STA (DisplayBaseAddr), Y	; Use DisplayBaseAddr as a pointer and store the accumulator into VRAM
			INY				; Next byte
			BEQ .ClearRemainingVRAM		; Did we roll over the Y register? If so, clear the remaining VRAM
			JMP .ClearWriteToVRAM1		; Finish clearing VRAM
			
.ClearRemainingVRAM	LDA DisplayBaseAddr + 1		; Load the high byte of the VRAM address into the accumulator
			ADC #$1				; Add one so we point to the next page
			STA DisplayBaseAddr + 1		; Write back the modified pointer
			LDA #$00			; Reset the accumulator to 0
			
.ClearWriteToVRAM2	STA (DisplayBaseAddr), Y	; Write the accumulator into VRAM
			CPY DisplayEndAddr		; Have we reached the end of VRAM?
			BEQ .ClearCleanup		; If so, clean up what we changed
			INY				; Next byte
			JMP .ClearWriteToVRAM2		; Finish clearing VRAM
			
.ClearCleanup		LDA DisplayBaseAddr + 1		; Load the high byte of the VRAM pointer
			SBC #$1				; Subtract one so we go back to the page it starts on
			STA DisplayBaseAddr + 1		; Write back the pointer
			RTS				; Return to caller

; Writes the emulated video memory to the simulator's console output address
; =============================================================================
EmuDisplayCopy						; Write the first page of VRAM to the simulator console
			LDA #$00
			LDY #$00
			
.CopyCopyVRAMPage1	LDA (DisplayBaseAddr), Y
			INY
			BEQ .CopyRemainingVRAM
			STA $E001
			JMP .CopyCopyVRAMPage1

; BUGBUGBUG
; LDA DisplayBaseAddr + 1 Loads 02 into the accumulator, yet
; ADC #$1 causes the accumulator to read 4 instead of 3
.CopyRemainingVRAM	LDA DisplayBaseAddr + 1		; Load our VRAM pointer's high byte into the accumulator
			ADC #$1				; Add one to set the next page
			STA DisplayBaseAddr + 1		; Save the modified pointer back into ram
			
.CopyVRAMPage2		LDA (DisplayBaseAddr), Y
			INY
			BEQ .CopyCleanup
			STA $E001
			JMP .CopyVRAMPage2
			
.CopyCleanup		LDA DisplayBaseAddr + 1
			SBC #$1
			STA DisplayBaseAddr + 1
			RTS
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

In general, before using ADC, you should use CLC to clear the carry bit. Not using CLC is OK as long as you can absolutely be sure that the carry bit is clear. Conversely, if the carry bit is guaranteed to be set, you can just ADC #$00 to increment the A register.
asmlang_6
Posts: 53
Joined: 20 Jul 2005
Location: Hawaii

Re: Best way to learn 6502 assembly without real hardware?

Post by asmlang_6 »

kc5tja wrote:
Lazy1 wrote:
Oops, forgot to look on the tools page...
I found a simulator but what about building 6502 based computers?
Once you learn those two things, then you're ready to basically just dive right in. There is no right or wrong way to build a 6502-based computer.
Here's some tips:
  • Wire your system together on a breadboard. You can easily insert/remove components without soldering, and they will stay on pretty good (I was building a 6502 system on a breadboard, and I turned the breadboard upside down and none of the components fell off!). But one warning: don't put the parts in too good, or you will have lots of frustration when trying to remove chips.
  • Take your time to make a memory map. Since the 6502 uses memory-mapped I/O, you will have to factor that in. Most 6502 systems use the 74LS138 3-to-8 decoder for memory mapping (usually priced at around 50 cents). The 74LS138 is connected to the 6502 by wiring lines S0, S1, and S2 (pins 1, 2, and 3 respectively) to A15, A14, and A13 (note: counting from A0 here) on the 6502. Then, connecting /Y1 to /CS of a chip should map it to $0000-$1FFF, /Y2 to $2000-$3FFF, etc.
Sam

---
"OK, let's see, A0 on the 6502 goes to the ROM. Now where was that reset vector?"
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

Thanks for the info but I don't understand quite a bit of what you said.
Still learning 6502 assembly after a short break so once that is done hopefully I can learn how to build something which uses it.
User avatar
djmips
Posts: 17
Joined: 12 Jul 2005

6502 sim for learning basics

Post by djmips »

http://home.pacbell.net/michal_k/6502.html

This is a simulator for your PC. You can write small code, it will assemble and you can step through the results.
Lazy1
Posts: 9
Joined: 14 Jul 2004

Post by Lazy1 »

Yeah, thats the simulator I'm using now which didn't support display memory which is why I had to emulate it.
Actually, I should probably re-write that along with some printf and console routines.
User avatar
djmips
Posts: 17
Joined: 12 Jul 2005

printf and console

Post by djmips »

Check out the liba.65s example for input/output to the In/Out window. I agree that it's not the best and if it had better I/O and graphics output that would be a lot of fun.
Memblers
Posts: 64
Joined: 16 Jan 2003
Location: Indianapolis
Contact:

Post by Memblers »

I learned 6502 by running my programs on NES emulators. I can use the real hardware now that I built my own cartridge. :)

If you're willing to learn the quirks of that system (which is mostly related to the graphics), it's a good one to use. NMOS 6502 (no decimal mode though), good sound, decent tiled graphics/scrolling, and 64 sprites. It's also very common hardware if you want a real one (and many companies still make clone systems today).
Post Reply