Seyed Masoud Hosseini · Overview · Study log · Ideas · Transcript · RSS feed

Embedded Systems, 6502 breadboard computer · Lecture 3 of 29 · 15:35

Part 3: Assembly language vs. machine code

Assembly language vs. machine code — 6502 part 3 on YouTube

Study guide

What this lecture covers

Having hand-encoded machine code onto an EEPROM in the previous videos, this lecture shows why that approach doesn't scale and introduces assembly language as the practical way to program the 6502. It uses the vasm assembler to translate readable mnemonics like LDA and STA into the same raw opcode bytes used before.

The lecture also covers the assembler directives needed to reproduce a valid ROM image (padding, origin address, reset vector) and shows how labels remove the need to manually calculate jump target addresses. It ends by using the newly-comfortable workflow to write a slightly different LED program using a rotate instruction.

Key ideas

  • Assembler: a program that converts human-readable assembly mnemonics into the raw machine code bytes a processor executes, removing the need to look up opcodes by hand.
  • Immediate vs. zero-page addressing: LDA #$FF (opcode $A9) loads the literal value $FF, while LDA $FF (opcode $A5) loads whatever is stored at memory address $00FF; the # and $ symbols in vasm syntax change the opcode generated.
  • .org directive: tells the assembler what memory address the following code should be treated as occupying, needed here because the EEPROM appears at $8000 and up even though its own bytes start at 0.
  • .word directive: writes a 16-bit value (such as the reset vector) into the output in the processor's little-endian byte order automatically.
  • Labels: named markers (like loop or reset) that let the assembler calculate addresses for jumps automatically, avoiding fragile hard-coded addresses that break when code changes.
  • -f bin output format: the assembler option that produces a raw binary file rather than a human-readable listing, which is what the EEPROM programmer needs.
  • Rotate instruction (ROR): shifts the bits of the accumulator right by one, moving the lowest bit into the processor's carry flag and the carry flag into the top bit.

Walkthrough

Why hand-written machine code doesn't scale (0:00)

The lecture reads back the program from the previous video's EEPROM as raw hex bytes and points out that no one writes real software this way. It introduces vasm as the assembler that will translate readable assembly into the same machine code.

Assembling a minimal program and the immediate-mode trap (1:00)

A two-line assembly program is compiled with vasm, first producing a text listing, then a raw binary via the -f bin option. Removing the # symbol from LDA #$FF is shown to silently change the opcode from immediate-mode load to zero-page load, a subtle but important syntax detail.

Reproducing a full ROM image with directives (6:02)

The .org $8000 directive tells the assembler the code's true starting address in the processor's memory map, and .word directives place the reset vector and padding to reach the required 32,768-byte file size.

Using labels instead of hard-coded addresses (10:05)

Labels such as loop and reset replace manually calculated jump targets like $8005, making the code resilient to future edits and easier to read.

Writing and testing a rotate-based LED program (11:05)

A new program outputs $50 to the LEDs, then uses ROR in a loop to rotate the bit pattern right on each pass. After assembling, writing to the EEPROM, and powering the circuit, the LEDs visibly rotate, confirming the carry-bit behavior described in the datasheet.

Before you watch

  • Watch parts 1 and 2 first, since this video assumes the breadboard wiring, EEPROM, and VIA setup already built there.
  • Familiarity with hexadecimal and the 6502 opcode table from part 2 is helpful for following the addressing-mode discussion.

Check your understanding

  1. What is the practical difference between LDA #$FF and LDA $FF in vasm syntax, and why does it matter?
  2. Why does the code need an .org $8000 directive even though the EEPROM's own bytes start at address 0?
  3. How do labels make the jump instruction at the end of the loop more maintainable than a hard-coded address?
  4. What happens to the carry flag during a ROR instruction, and how does that show up as a "hidden ninth bit"?
  5. Why must the final ROM image be exactly 32,768 bytes long?

Chapters

From the YouTube description

Schematics, datasheets, kits, and more at https://eater.net/6502
More on vasm: http://sun.hasenbraten.de/vasm

Part 1: https://www.youtube.com/watch?v=LnzuMJLZRdU
Part 2: https://www.youtube.com/watch?v=yl8vPW5hydQ
Part 3: This video!
Part 4: https://www.youtube.com/watch?v=FY3zTUaykVo
Part 5: https://www.youtube.com/watch?v=xBjQVxVxOxc
Part 6: https://www.youtube.com/watch?v=i_wrxBdXTgM
Part 7: https://www.youtube.com/watch?v=omI0MrTWiMU

Support these videos on Patreon: https://www.patreon.com/beneater or https://eater.net/support for other ways to support.

------------------

Social media:
Website: https://www.eater.net
Twitter: https://x.com/beneater
Patreon: https://patreon.com/beneater
Reddit: https://www.reddit.com/r/beneater

Special thanks to these supporters for making this video possible:
Adam Lininger
Adrien Friggeri
Alex Catchpole
Andrew R. Whalley
Anthony Cuccia
Armin Brauns
BakerStaunch
Beau-James Erion
Ben Dyson
Ben Kamens
Ben Williams
Bradley Pirtle
Brian Wanda
Bryan Brickman
Carlos Ambrozak
Chad Fertig
Christopher Blackmon
Clayton Parker Coleman
Daniel Tang
Dave Walter
David Boardman
David H. Friedman
David House
David Turner
Dean Winger
Debilu Krastas
Dušan Dželebdžić
Dzevad Trumic
Eric Brummer
Eric Dynowski
Eric Twilegar
Erik Broeders
Eugene Bulkin
Foaly
Gabriel Lafond-Thenaille
HaykH
Ian Tait
Ivan Sorokin
Jackson Warren
JavaXP
Jay Binks
Jayne Gabriele
Jeremy Wise
Jimmy Campbell
Joel Messerli
Joel Miller
Joern Heidenreich
Jordan Scales
Joshua King
Justin Dubs
Justin Duch
Kefen
Kent Collins
Manne Moquist
Marcus Classon
Mats Fredriksson
Michael
Michael Burke
Michael Garland
Michael Tedder
Miguel Ríos
Nathan Wachholz
Nicholas Moresco
Onion Sniffer
Paul Pluzhnikov
Paul Randal
Peter Simard
Philip Hofstetter
Randy True
Richard Wells
Rob Bruno
Robert Blackshaw
Robert Butler
Ross
Sachin Chitale
Sam Rose
Scott
Sergey Ten
Sever Banesiu
SonOfSofaman
Stefan Nesinger
Stefanus Du Toit
Stephen Smithstone
Steve Jones
Steve Gorman
Steven Pequeno
Thomas Ballinger
Tom Burns
Vladimir Kanazir
Warren Miller
fxshlein
hunter wright
xisente
Örn Arnarson

← Part 2: How CPUs read machine code · Part 4: Connecting an LCD to our computer →