Ich suche ein Tool, mit dem ich schrittweise Assembler-Code ausführen kann.
Es sollte ausgewählte Speicherstellen als Binär-, Hex- und Dezimalzahlen anzeigen, um zu zeigen "was sich da tut".
Es muss jetzt nicht unbedingt speziel für den C64 sein, wäre aber besser.
Ich möchte testen, ob bei Berechnungen die Bits richtig hin- und hergeschoben werden 
Hier wäre die Auskunft von deiner Seite sinnvoll, ob Du in Maschinensprache gerade erst (wieder neu) einsteigst, oder ob Du von späteren Rechnern (Amiga, PC) das Arbeiten in aufwendigeren Debuggern wie in @oobdoo's Beitrag gewohnt bist.
Beim (Neu-)Einstieg tut's eigentlich erstmal jeder native Feld-Wald-und-Wiesen-Monitor (gerne auch ohne Anführungszeichen). Nicht jeder von denen kommt mit einem Einzelschrittmodus daher, es gibt aber immer die Möglichkeit, Einzelbefehle durch Breakpoints zu trennen und so durch das Programm zu steppen - sobald das Programm Tastatur und Bildschirm bedient, wird's allerdings komplizierter, da der Monitor ja eine Nebenwirkung erzeugt.
Damit kann Du dann ohne weiteres die Wirkung der Einzelbefehle nachvollziehen und zwischendrin auch schauen, was sich im Speicher so tut, eben per Kommandozeile.
Auf dem VC-20 hab ich auf solche Weise z.B. die Abarbeitung einer eigenen Quadratwurzel-Routine, eingehängt in die USR()-Funktion nachvollzogen - vorweg erstmal der Sourcecode:
- .Sqrt
- JSR $BC1B ; FAC#1 runden
- JSR $BC2B ; Vorzeichen von FAC#1 prüfen
- BEQ Sqrt_03 ; =0? Dann sofort beenden! (SQR(0)=0)
- BPL Sqrt_00 ; weiter, wenn positiv, sonst
- JMP $B248 ; ?ILLEGAL QUANTITY ERROR anzeigen
- .Sqrt_00
- LDA $61
- STA $FB ; Exponent-Byte des Arguments merken
- AND #$01
- ORA #$80
- STA $61 ; Argument X auf den Bereich [0.5,2.0[ reduzieren
- LDA #$04
- STA $FC
- LDX #Sqrt_04 MOD 256
- LDY #Sqrt_04 DIV 256
- JSR $BBD4 ; FAC#1 nach Sqrt_04 (X: reduziertes Argument) speichern
- LDA #$BC
- LDY #$B9
- BNE Sqrt_02 ; mit Y=1 als erste Annäherung starten,
- .Sqrt_01 ; und Schleife 4x ausführen, dabei jedesmal Y=(Y+X/Y)/2.0 berechnen
- LDX #Sqrt_05 MOD 256
- LDY #Sqrt_05 DIV 256
- JSR $BBD4 ; FAC#1 nach Sqrt_05 (Y: Zwischenergebnis) speichern
- LDA #Sqrt_04 MOD 256
- LDY #Sqrt_04 DIV 256
- JSR $BB0F ; FAC#1 = X/Y
- LDA #Sqrt_05 MOD 256
- LDY #Sqrt_05 DIV 256
- .Sqrt_02
- JSR $B867 ; FAC#1 = Y+X/Y (=1+X beim ersten Einsprung)
- DEC $61 ; FAC#1 durch 2 teilen
- DEC $FC
- BNE Sqrt_01
- LDA $FB ; Exponent des Ergebnisses ausrechnen
- LSR A
- ADC #$40
- STA $61
- .Sqrt_03
- RTS
- .Sqrt_04
- EQUB 0:EQUB 0:EQUB 0:EQUB 0:EQUB 0
- .Sqrt_05
- EQUB 0:EQUB 0:EQUB 0:EQUB 0:EQUB 0
Alles anzeigen
Die Idee ist jetzt, nachzuvollziehen, was sich bei den Schleifendurchläufen in Y := Sqrt_05 tut.
Ich hab in der nachfolgenden Reihe von Screenshot die Routine erstmal 'batch-assembliert' - dazu wird die Eingabe des Monitor zeitweilig in eine SEQ-Datei umgelenkt:

Sobald der Batch abgelaufen ist, stellt eine kleine Hilfsroutine die Standard-Ein-/Ausgabe wieder her, schließt die Datei und kehrt zu BASIC zurück:

Jetzt ein etwas tieferer Blick in den assemblierten Code um das Äquivalent der Zeile "JSR $BBD4 ; FAC#1 nach Sqrt_05 (Y: Zwischenergebnis) speichern" zu finden ...

... und wir werden fündig bei $02CD - da der Aufruf hier ins VC-20-BASIC-ROM geht, ist es der Befehl JSR $DBD4:

Das Zwischenergebnis in Y geht nach $02F1. Der Code wird nun instrumentiert, damit wir uns das Zwischenergebnis in jedem Schleifendurchlauf ansehen können. Eine Kopie von JSR $DBD4 wird an anderer Stelle hingeschrieben und mit den Befehlen BRK/NOP/RTS abgeschlossen. Dieser "Rucksack" wird dann von einem JSR-Befehl angesprungen, der die Stelle des originalen JSR $DBD4 einnimmt:

Wieder in BASIC zurück, geben wir PRINTUSR(2) ein um die Quadratwurzel von 2 auszurechnen. Der PRINT-Befehl steht hinter einer Zeile von Doppelpunkten, weil der Monitor auch den BASIC-Eingabepuffer nutzt und wir am Ende keinen ?SYNTAX ERROR haben wollen.
Während der Ausführung reduziert die Routine das Argument in den Bereich größer gleich 0,5 und kleiner 2, intern rechnet es also die Wurzel von 0,5 aus und korrigiert anschließend den Exponent.

Der Breakpoint ist jetzt das erste mal aufgerufen worden und bei $02F1 ist "$80 $40 $00 $00 $00" gespeichert. Mit G und M zeigen wir die nächsten Zwischenergebnisse an bis die Routine fertig ist und die Kontrolle an den BASIC-Interpreter zurückgibt, ...

... mit der Ausgabe von PRINT sauber angehängt an das letzte G-Kommando. 
Die drei Zwischenergebnisse im Fließkommaformat entsprechen diesen Zahlen:
>02F1 80 40 00 00 00 ^= 0.75
>02F1 80 35 55 55 55 ^= 0.708333333
>02F1 80 35 05 05 05 ^= 0.707107843
Nach diesen drei Durchläufen ist der nächste Wert im Fließkommaakkumulator schon innerhalb der Genauigkeit und nach Korrektur der Exponenten wird 1.41421356 als Ergebnis ausgegeben.