Welche Assembler/Compiler gibt es zur Programmierung eines Apple 1 - nicht für Apple 2 etc. pp.
Dabei geht es primär um Cross Entwicklung auf PC.
Ideal Open Source und C.
cc65 unterstützt leider nur Apple 2 etc.
Peter
Welche Assembler/Compiler gibt es zur Programmierung eines Apple 1 - nicht für Apple 2 etc. pp.
Dabei geht es primär um Cross Entwicklung auf PC.
Ideal Open Source und C.
cc65 unterstützt leider nur Apple 2 etc.
Peter
cc65 besteht grundsätzlich aus zwei Bestandteilen:
1. Der Codegenerierung. Der C Compiler 'cc65' erzeugt aus C Quelltexten Assembler Code, der dann durch den Makro Assembler 'ca65' zu Objektdateien assembliert wird. Zum Schluß verbindet der Linker 'ld65' die Objektdateien zum fertigen Programm. Dies ist i.A. völlig unabhängig vom Rechner, für den das Programm sein soll. Statt die Programme einzeln aufzurufen kann man das auch 'cl65' überlassen.
2. Die C Bibliothek. Da sind dann Funktionen wie printf() implementiert, Diese C Bibliothek hat zwar auch ein paar Teile, die unabhängig vom Rechner sind - z.B. memcpy(), aber der Großteil ist für jeden Rechner anders.
Wenn nun also gesagt wird, dass cc65 den Apple I nicht unterstützt, dann bedeutet das, dass die Apple I-spzifischen Teile der C Bibliotheken fehlen. So weit so schlecht. Nur ist es aber auf der anderen Seite so, dass ein Assembler wie xa "noch schlechter" ist, denn der hat weder eine fertige Bibliothek für den Apple I noch die Möglichkeit, ein Programm oder Teile eines Programms in C zu schreiben.
Oder anders herum gesagt, wenn man eigentlich gerne mit C arbeiten will, dann ist cc65 auch ohne Unterstützung für den gewünschten Rechner immer noch viel besser als ein 0815-Assembler - zumal cc65 ja auch einen konkurrenzfähigen Assembler beinhaltet (und die Mischung von C und Assembler toll unterstützt).
Es gibt ein ganze Reihe von Möglichkeiten, wie man nun konkret vorgehen kann, um in C für einen Rechner zu programmieren, den cc65 "nicht unterstützt". Die zumindest für die ersten Schritte einfachste dürfte aus diesen Punkten bestehen:
1. Nutzung des 'none' Targets in Stil von 'cl65 -t none ...'. Damit macht man zunächst "keine" Aussagen über den Zielrechner.
2. Explizite Definition des vom Programm zu verwendenden Speichers (weil cc65 das bei einem "nicht unterstützten" Rechner ja nicht wissen kann).
2.1 Niedrigste zu verwendende Adresse: --start-addr $xxxx
2.2 Höchste zu verwendende Adresse: -Wl -D,__STACKSTART__=$xxxx
2.3 Niedrigste zu verwendende Zeropage Adresse: -Wl -D,__ZPSTART__=$xx
Siehe https://github.com/cc65/cc65/blob/master/cfg/none.cfg#L1-L12 für die Arithmetik dahinter.
3. Nutzung von _sys() zum Aufruf vom ROM-Funktionen, z.B. für die Ausgabe eines Zeichens auf dem Bildschirm. Siehe https://cc65.github.io/doc/funcref.html#_sys und https://github.com/cc65/cc65/b…er/include/6502.h#L72-L79
Um z.B. eine (hypothetische) ROM Funktion an Adresse $FEDC mit 65 im Accumulator aufzurufen, könnte man schreiben:
struct regs r;
r.a = 65;
r.pc = $FEDC;
_sys(&r);
4. Nutzung von PEEK()/POKE() zum Zugriff auf bekannte Adressen. Siehe https://cc65.github.io/doc/funcref.html#ss2.36
Viel Spaß!
xa kann kein Listing erzeugen??!
So etwas benötigt man doch immer!
Von hier: http://xi6.com/projects/asmx/
habe ich die ältere Version 1.5 für 6502 genommen - der erzeugt zumindest mal ein Listing.
---
Welche 6502 Assembler nutzt ihr denn so?
Und welche Simulatoren?
(Also hex/Bin laden, Disassembler, Steps durch das Programm mit Register+Flag Anzeige)
LG Peter
Welche 6502 Assembler nutzt ihr denn so?
Bit Shift Assembler
https://github.com/Edilbert/BSA
Der erzeugt natürlich auch ein schönes Listing und der Entwickler Bit Shifter ist auch hier im Forum aktiv.
Danke. Sehr interessant.
Warum man >2000 Zeilen C Code schreiben kann, aber keine 20 Zeilen readme.txt entzieht sich allerdings meinem Verständnis
Das am Anfang des C Sourcecodes vieles steht ist gut!
Aber gerade .STORE ist da angegeben mit:
.STORE BASIC_ROM,$2000,"basic.rom" write binary image file "basic.rom"
Aber erst nach dem Studium des Quelltextes, kann ein C Sourcecode Leser sehen:
char *ParseStoreData(char *p)
{
int Start,Length,i;
char Filename[80];
if (Phase < 2) return p;
p = EvalOperand(p,&Start,0);
if (Start < 0 || Start > 0xffff)
{
ErrorMsg("Illegal start address for STORE %d\n",Start);
exit(1);
}
p = NeedChar(p,',');
if (!p)
{
ErrorMsg("Missing ',' after start address\n");
exit(1);
}
p = EvalOperand(p+1,&Length,0);
if (Length < 0 || Length > 0x10000)
{
ErrorMsg("Illegal length for STORE %d\n",Length);
exit(1);
}
p = NeedChar(p,',');
if (!p)
{
ErrorMsg("Missing ',' after length\n");
exit(1);
}
p = NeedChar(p+1,'"');
if (!p)
{
ErrorMsg("Missing quote for filename\n");
exit(1);
}
Display More
=> d.h.:
;.STORE <startaddress>,<length>,"filename"
.STORE $280,$100,"out.bin"
Dabei MUSS man eine Länge angeben - für Eproms sicher ok. Für raw binare aber unschön.
Hier fehlt ein Parameter, der als Platzhalter für die Filelänge dient!
Genauso die Startadresse - kann mal doch aus der ORG / * = Anweisung nehmen..
(z.B. -1 für beide = Start aus org/*= oder 0 und Länge = Binärlänge)
Noch ein weiterer Punkt. Source muss zwingend .asm heißen.
Stört nicht, muss man aber wissen.
Ansonsten schöner Assembler!
LG Peter
Zu ca65 gibt es https://cc65.github.io/doc/ca65.html
Sowohl xa als auch asm6502 akzeptieren inc alleine, obwohl das eine 65C02 Anweisung ist, ohne zu warnen.
bsa wirft Error aus, wenn 6502 aktiv ist = richtig!
Dem asm6502 habe ich mal schnell beigebracht raw binary auszugeben - siehe zip - falls es wer braucht.
Als Simulator habe ich py65mon bis jetzt: https://github.com/mnaberez/py65
LG Peter
Habe noch wichtige Hinweise zum bsa erhalten:
So geht es mit .STORE:
START = $0801
* = START
.STORE START,EndOfProgram-START,"program.prg"
Dadurch bekommt man ein Binary mit nur der Programmlänge.
LG Peter
Wenn man ein CBM Programm erstellen will, ist es nützlich auch den Pseudo Op:
.LOAD
zusätzlich zum .STORE zu verwenden.
Dann wird die Anfangsadresse des Binary vor das Binary geschrieben, dem CBM Standard für PRG Dateien entsprechend.
START = $0801
* = START
.LOAD
.STORE START,EndOfProgram-START,"program.prg"
schreibt die Bytes $01 $08 und dann den im STORE Befehl angegebenen Bereich.
Sowohl xa als auch asm6502 akzeptieren inc alleine, obwohl das eine 65C02 Anweisung ist, ohne zu warnen.
bsa wirft Error aus, wenn 6502 aktiv ist = richtig!
Es gibt einen immerwährenden Disput um die Adressierung A (Accumulator) unter den 6502 Programmierern.
Ich bevorzuge die Schreibweise:
weil diese Schreibweise im ersten offiziellen Handbuch zur 6502 Programmierung von MOS so vorgegeben wurde.
Da aber viele Programmierer darauf beharren diese Befehle ohne 'A' zu schreiben, bin ich pragmatisch vorgegangen:
Der BSA akzeptiert beide Schreibweisen. Somit werden die Befehle
als synonym aufgefasst.
Aber
sind wie von Peter beschrieben, keine Instruktionen, die der 6502 beherrscht.
Hmm. Irgendwas geht noch nicht so, wie es soll:
ichs-iMac:bsa ich$ ./bsa rnd8
*******************************************
* Bit Shift Assembler 12-Aug-2020 *
* --------------------------------------- *
* Source: rnd8.asm *
* List : rnd8.lst *
* -d:Off -i:Off -n:Off -x:Off *
*******************************************
*** Error in file rnd8.asm line 2:
Illegal length for STORE 16711680
ichs-iMac:bsa ich$
Display More
Code:
;.STORE <startaddress>,<length>,"filename"
.STORE START,EndOfProgram-START,"out.bin"
START = $280
LG Peter
Display MoreHmm. Irgendwas geht noch nicht so, wie es soll:
CodeDisplay Moreichs-iMac:bsa ich$ ./bsa rnd8 ******************************************* * Bit Shift Assembler 12-Aug-2020 * * --------------------------------------- * * Source: rnd8.asm * * List : rnd8.lst * * -d:Off -i:Off -n:Off -x:Off * ******************************************* *** Error in file rnd8.asm line 2: Illegal length for STORE 16711680 ichs-iMac:bsa ich$
Code:
;.STORE <startaddress>,<length>,"filename"
.STORE START,EndOfProgram-START,"out.bin"
START = $280
LG Peter
EndOfProgram ist keine vordefinierte Variable sondern sollte als Beispiel dienen.
Jeder beliebige Name kann verwendet werden. Auch START ist nicht reserviert sondern ein Beispiel.
Ein Feature, das ich nicht mehr missen möchte, ist es lokale Label und Konstanten zu verwenden.
Wenn man einen Bereich mit "Module" und "EndMod" deklariert, so lassen sich darin lokale
Variablen verwenden, deren Gültigkeitsbereich (Scope) auf das Module beschränkt ist.
Lokale Namen müssen zur Unterscheidung von globalen Namen mit einem Unterstrich _ beginnen.
Das erspart die Suche nach immer neuen Labelnamen und macht den Code übersichtlicher.
Ein Beispiel mit zwei Modulen, die konfliktfrei beide das Label "_loop" verwenden.
*****************
Module LAC_To_LDA
*****************
PHX
LDX #3
_loop LDA Long_AC,X
STA Long_DA,X
DEX
BPL _loop
PLX
RTS
EndMod
*******************
Module LAC_Plus_LCT
*******************
PHX
LDX #252 ; use ZP wrap around
CLC
_loop LDA Long_AC+4,X
ADC Long_CT+4,X
STA Long_AC+4,X
INX
BNE _loop
PLX
RTS
EndMod
Display More
Ah. Definition mit:
EndOfProgram = *
In etwa?
Peter
Ja, richtig, wobei das "= *" funktioniert aber überflüssig ist, weil das Label ja schon durch die Position
den Wert des PC erhält.