8-Bit-Breadboard-Computer auf Basis einer 6502-CPU - Von Maschinensprache zu Assembler

Bisherige Artikel dieser Serie - hier könnt ihr nochmal alle Grundlagen nachlesen, falls ihr jetzt erst einsteigt: Bisher haben wir unsere 6502-CPU ja immer in Maschinensprache programmiert, was bedeutet: Unser letztes Maschinenspracheprogramm sah deswegen so aus: Adr. Assembler Bytecode (hex) Bedeutung (hex) 8000 LDA# 01 A9 01 lade 01 (rechte LED) in den Akku 8002 STA 7000 8D 00 70 speichere den Akku-Inhalt an RAM-Adresse 7000, die rechte LED sollte nun leuchten 8005 LDA# 07 A9 07 wir müssen 7 mal nach links shiften, bis die LED ganz links angekommen ist 8007 ROL 7000 <-. 2E 00 70 alle Bits in 7000 werden eine Stelle nach links verschoben, | LED wandert nach links 800A DECA | 3A erniedrigt den Akku um eins 800B BNEr --' D0 FA nach 7 Durchläufen ist der Akku auf Null und BNE (Branch If Not Equal Zero) springt nicht mehr zurück. BNE ist ein 2-Byte-Befehl, der 1-Byte Parameter gibt den Offset zum aktuellen PC an. Sprünge zurück haben einen negativen Offset, der als Zweier- komplement angegeben werden muss. 0xFF ist -1, 0xFA ist -6 800D LDA# 07 A9 07 wir müssen die LED-Position 7 mal nach rechts verschieben, bis die LED wieder ganz rechts angekommen ist 800F ROR 7000 <-. 6E 00 70 alle Bits in 7000 werden eine Stelle nach rechts verschoben, | LED wandert nach rechts 8012 DECA | 3A erniedrigt den Akku um eins 8013 BNEr --' D0 FA nach 7 Durchläufen ist der Akku auf Null und BNE springt nicht mehr zurück 8015 JMP 8005 4C 05 80 und wieder zum Scrollanfang zurück, dann geht es wieder nach links usw. usf. Bzw. genauer gesagt sind das die Notizen die zu dem Maschinenspracheprogramm geführt haben, denn das Programm ist eigentlich nur A9 01 8D 00 70 A9 07 2E 00 70 3A D0 FA A9 07 6E 00 70 3A D0 FA 4C 05 80 Aber das geht alles auch ein bisschen einfacher.

Der nächste Schritt in der Programmiersprachen-Evolution: Assembler

Und zwar mit Assembler. Dann sieht unser Programm nämlich so aus: ; K.I.T.T. Lauflicht auf die 8-LED-Ausgabe oben rechts auf dem Breadboard org $8000 ; Programmstartadresse (von der CPU aus gesehen) ; --- Konstanten: IO-Adressen --- LED: equ $7000 ; 8-LED-Ausgabe, hört aber auf alles von $7000 bis $7fff start: lda #$01 ; rechts anfangen sta LED scroll: lda #$07 ; 7x nach links left: rol LED dec A bne left lda #$07 ; 7x nach rechts right: ror LED dec A bne right jmp scroll; und wieder nach links Die Vorteile liegen auf der Hand: Was wir da nicht an Zeit und Mühe sparen. Außerdem sind die Programme viel lesbarer.

Okay, einen Nachteil hat es: wenn wir debuggen und uns den Maschinensprachecode im Sniffer anschauen, z. B. bei diesem Maschinensprache-Programmausschnitt 8000 A9 r LDA# 8001 01 r 8002 8D r STA 8003 00 r 8004 70 r 7000 00 W 7000 01 W 8005 A9 r LDA# 8006 07 r 8007 2E r ROL 8008 00 r 8009 70 r 7000 01 r 7000 00 W 7000 02 W 800A 3A r DECA 800B D0 r 800B D0 r BNEr 800C FA r dann würde uns die Vorarbeit schon helfen, denn dann wüssten wir z. B. gleich, wohin der BNE bei 800B mit FA verzweigt.

Aber: warum diese Arbeit (Übersetzung in Maschinensprache) immer machen, wenn es doch ausreicht, sie sich zu machen, wenn es unbedingt nötig ist. Vielleicht unser Programm ja auch gleich tadellos und wir müssen gar nicht debuggen, oder nicht so tief, oder nicht so viel.

Und den nervigen Teil der Arbeit, nämlich das Heraussuchen der Befehle für die Byte-OpCodes nimmt uns ja glücklicherweise der Deassemblierungsteil unseres Sniffers ab.

Assembler gibt es mehrere auf dem Markt, die meisten frei und kostenlos. Mein erster Blick ging natürlich Richtung WDC, von dem ja auch unsere CPU W65C02 stammt.

Der WDC-Assembler und Linker

Der WDC 6502er hat ja ein paar zusätzliche OpCodes, die im Original MOS 6502 noch nicht vorhanden sind. Und wenn es vom Hersteller des Chips einen Assembler gibt, dann kann man davon ausgehen, dass dieser all diese schönen, neuen Befehle auch unterstützt.

Und für wahr: WDC bietet einen Assembler an, ja sogar ein ganzes Paket an Tools, kostenlos und aus dem Internet herunterladbar. Man muss sich zwar registrieren bzw. seine e-mail-Adresse angeben, aber ansonsten geht der Download ganz problemlos.

Im Tookilt findet man außer Entwicklungsumgebungen für die WDC-Boards auch einen Simulator und für uns interessant: einen Assembler und einen Linker. Dazu gibt es auch eine fast 100-seitige Dokumentation als PDF. NAtürlich auf englisch, aber diesmal Angabe der e-mail downloadbar.

Nachdem man das Toolkit in ein Verzeichnis seiner Wahl (bei mir d:\6502\wdc, besser aber c:\wdc, weil die PATH-Variable in Windows bei der Installation hart darauf gesetzt wird und dann nicht per Hand angepasst werden muss) entpackt hat, sollte man den Ordner ...\Tools\bin ansteuern. Dort finden sich die für uns interessanten Exes: Verzeichnis von d:\6502\wdc\Tools\bin 24.09.2016 01:33 1.816.855 easysxb.exe 29.06.2008 23:37 1.905.365 srec_cat.exe 30.06.2017 18:29 4.037.632 tide.exe 07.02.2006 02:25 116.224 WDC02AS.exe 07.02.2006 01:25 104.960 WDC02CC.exe 07.02.2006 02:23 75.776 WDC02OP.exe 07.02.2006 02:24 116.224 WDC816AS.exe 19.01.2006 23:38 178.688 WDC816CC.exe 06.02.2006 22:38 98.304 WDC816OP.exe 15.09.2010 21:05 243.712 wdcdb.exe 22.12.2005 23:46 65.536 WDCLIB.exe 25.04.2006 00:40 99.328 WDCLN.exe 19.01.2006 21:36 66.048 WDCOBJ.exe 19.01.2006 21:36 62.464 WDCSYM.exe WDC02AS.exe ist der Assembler für die W65C02 CPU. Dieser assembliert unseren Assembler-Sourcecode (.asm) und macht daraus .obj-Dateien. WDCLN.exe macht aus dem .obj-File dann ein .bin-File, welches unser Maschinensprachecode enthält.

Versucht es mal: Gebt in einem Texteditor eurer Wahl das Assembler-Programm von oben ein und speichert es als 0-LED-Lauflicht.asm. Baut viellicht noch absichtlich einen Syntax-Fehler ein. Öffnet dann eine Eingabeaufforderung und gebt ein WDC02AS.exe 0-LED-Lauflicht.asm Jetzt sollte der Assembler melden, an welcher Stelle im Code er den Syntax-Fehler gefunden hat. Korrigiert ihn und assembliert neu. Erscheint dann nur noch WDC 65C02 Assembler Version 3.49.1 Feb 6 2006 17:25:36 Copyright (C) 1992-2006 by The Western Design Center, Inc. habt ihr es geschafft und der Assembler hat ein .obj-File erstellt, das ungefähr so aussieht:



Ich habe den für uns interessanten Teil, nämlich das Maschinenspracheprogramm, einmal blau markiert. Der Rest interessant uns aber herzlich wenig. Um nicht immer zu schauen, an welcher Stelle genau unser Maschinencode steht, benutzen wir den Linker: WDCLN 0-LED-Lauflicht.obj -HB WDC 65C816 Linker Version 3.49.1 Apr 24 2006 15:40:38 Copyright (C) 1992-2006 The Western Design Center, Inc. Section: ORG: ROM ORG: SIZE: CODE 008000 008000 18H ( 24) Total 18H ( 24) Der macht uns ein Binär-File. Allerdings packt er uns auch 32768 (0x8000) unnötige Null-Bytes an den Anfang, weil wir ja angegeben haben, dass ORG bei $8000 liegt:



Aber das macht ja nichts. Wir können ja ans Ende springen. Und dann wie gehabt die Bytes kopieren, in unserem Eprommer unser EEPROM lesen und im Hexeditor den Maschinencode an die richtige Stelle kopieren bzw. unser altes Programm überschreiben. War das alte PRogramm länger, können wir es ja wieder mit 0xEA auffüllen. Der Startvektor von 0x8000 bleibt ja gleich, so dass wir hier nicht nochmal Hand anlegen müssen.

Fertig. So viel menschenfreundlicher und einfacher mit einem Assembler.

Mal eben eine Entwicklungsumgebung programmiert

Ich habe mir die Sache sogar noch einfacher gemacht und ein kleines Programm geschrieben, dass mich beim assemblieren unterstützt, sozusagen eine kleine Entwicklungsumgebung:



Hier kann ich eine Programmbank zwischen 0 und 15 wählen. Ich habe dank des 512KB großen SST39SF040 16 mal 32 KB zur Verfügung, die ich ja per DIP-Schalter auf meinem Breadboard auswählen kann. Nachdem ich die eine Bank ausgewählt habe, kann ich den dort hinterlegten Assembler-Sourcecode editieren.

Es ist fertig, kann ich ihn speichern, und danach mit build assemblieren. Eventuelle Fehler werden dann rechts angezeigt. Sind alle Fehler besetigt, wird mit link der Linker aufgerufen, dessen Ausgabe darunter erscheint. Einmal evtl. Fehlermeldungen und zum anderen der Binärcode, unser Maschinenspracheprogramm. Das wird auch gleich als bank0.bin auf der Platte gespeichert. Beim upload werden die 16 Programmbänke dann zusammenkopiert in ein 512 KB großes Flash-File und die Eprommer-Software ferngesteuert, so dass das File autoamtisch geladen wird. Dann muss ich nur noch überprüfen, ob alles okay ist und kann das EEPROM flashen.

Das wird mir in Zukunft doch einiges an Zeit sparen. Wer mag schon ständig zwischen Editor, Command-Line und Eprommer-Software hin und herspringen? Das lenkt doch nur von der eigentlichen Entwicklung ab.

Das das Programm eine Eigenentwicklung ist, kann ich es natürlich beliebig erweitern. Wer weiß, vielleicht ist mir irgendwann langweilig und ich baue ein Syntax-Highlighting ein? Aber vorerst soll es mir so reichen.

Video

Ich habe mich an den PC gesetzt und nocheinmal alles in einem Video vorgeführt, was hier besprochen wurde. Viel Spaß beim Schauen:



Im nächsten Teil werden wir unseren Breadboard Computer um eine 3-fach-7-Segment-Anzeige erweitern.