Hallo,
ich bin auf https://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Square_root auf ein Assemblerprogramm zur Wurzelberechnung gestoßen. Dabei ist mir Bytedefinitionen mitten im Programm aufgefallen, auf die ich mir keinen Reim machen kann, hier ein kurzer Ausschnitt, das ganze Programm im Anhang:
1
add a,d ; 4
2
jr nc,sq6 ; 12 / 7
3
res 5,d ; 8
4
db 254 ; 7
5
sq6:
6
sub d ; 4
7
sra d ; 8
Mann kann ja einen Befehl durchaus auch als Byte definieren, aber hier macht das irgendwie keinen Sinn: 254 ist FEh und CMP n. "n" ist dann "sub d", also 92h. Kann sich da jemand einen Reim drauf machen, ich würde das gerne verstehen.
Das war früher so üblich, um die Codegröße zu reduzieren. Damit wird "sub d" ignoriert (cp setzt nur die Flags) und man spart sich den Sprung auf "sra d".
In lang sähe das so aus:
Das war früher so üblich, um die Codegröße zu reduzieren
Also ob das so üblich war, weiß ich nicht. Es ist richtig "dreckig" programmiert meiner Ansicht nach. Ich hab nie zu solch seltsamen Methoden gegriffen (greifen müssen).
Gut lesbarer Code war mir damals mit Z80 Assembler auch schon wichtig. Der oben gezeigte ist das definitiv nicht.
Eine andere Variante, bestens geeignet um Disassembler zu ärgern, waren Parameter direkt hinter einem Unterprogrammaufruf. Sowas wie
call stringcompare
db 'word' - letztes Byte mit Bit 7 gesetzt
Ein 8 KB Zwerg-Compiler bestand fast nur aus sowas in der Art. Das Unterprogramm hat sich den PC aus dem Stack geholt, inkrementell den String abgegrast, und hinterher wieder zurück geschrieben. Bei 8080/Z80 konnte man die wichtigsten solchen Aufrufe um 2 Bytes kürzen, indem man RST Opcodes an Stelle von CALL verwendete.
Also ob das so üblich war, weiß ich nicht. Es ist richtig "dreckig"
programmiert meiner Ansicht nach. Ich hab nie zu solch seltsamen
Methoden gegriffen (greifen müssen).
du Glücklicher, ich wollte PC1500 relokatibel programmieren um es in EEPROM in verschiedene Adressbereiche einbauen zu können.
Es gab aber kein jsr jump sub routine wo man mit ret/rts zurück kam!
Der aktuelle PC programm counter konnte auch nicht gelesen werden aber man konnte ihn in Register schieben diese dann auslesen und mußte nur noch vom Stack lesen und die Korrekturbytes am Stack manipulieren, waren wohl 6 bytes und so konnte man mit jump branch vorwärts oder rückwärts um x Byte springen um mit RTS oder RET genau da weiter zu machen von wo man herkam.
Danke, habs kapiert. Es geht also nur darum, sich das überspringen des
"sub d"-Befehls zu sparen. Very tricky.
Und wenn Du die Webseite, die Du verlinkt hattest, bis zum Ende gelesen haettest, haettest Du die Webseite des Autors (John Metcalf, http://www.retroprogramming.com) gefunden.
Noch ein Grund war, zu verhindern, dass jede Nase sofort kapiert, was der Code macht. Also zwischen Ende eines Unterprogramms und Anfang des nächsten ein "db ErstesByteDreiByteBefehl" brachte damals noch den Disassembler ins Schlittern.
Hallo!
Ich habe für einige kleine Z80-Systeme ganz ohne RAM Software geschrieben und dennoch Unterprogramme trotz fehlendem Stack verwendet.
Für diese Funktion wurde ein Register (IX oder IY) missbraucht.
Also z.B.:
....
LD IX,lab100 ;Returnadresse
JMP up100 ;oder JR up100
lab100: LD a,xy... ;hier gehts nach der Subroutine up100 weiter
....
up100:
LD DE,para3...
....
JP (IX) ;statt RET
Es funktionierte problemlos in einem 8-fach EPROM-Programmer für 2716 in der Serienproduktion zur Vervielfältigung aus einem Muster-2716.
Ich habe für einige kleine Z80-Systeme ganz ohne RAM Software
geschrieben und dennoch Unterprogramme trotz fehlendem Stack verwendet.
Für diese Funktion wurde ein Register (IX oder IY) missbraucht.
RCA hat das auf die Spitze getrieben mit dem CDP1802 ("COSMAC"). Der hatte 16 völlig gleichberechtigte Register, und jedes konnte Programmzähler sein. Zum Springen hat man einfach das Register umgeschaltet.
So hard-core-Optimieren haette ich selbst in meiner Jugendzeit nicht
gemacht, weil man den Code ein Jahr spaeter nicht mehr versteht.
Ist halt die Frage, ob man das noch zum Algo optimieren zählen sollte, oder eher unter die Rubrik "CPU-Architektur ausnutzen/"mißbrauchen". Denn Architekturunabhängig ist so ein Code sicher nicht.
Nur bei so schmalen Datenbussen wie in der 8 bit Ära konnte man Code überlappen, bei breiten Daten-Bussen geht das dann nicht mehr.
Mit Harvard Architektur hat man sogar getrennte Busse, kann also weiter 8 bit Daten schubsen mit bspw. 13 Bit Befehlscodebus (AVR?) .
IMHO lohn es sich eher die "mathematischen Tricks" (Numerik) zu lernen/verstehen, um dann schnell eine ausreichend genaue Berechnung runterzureissen; beispielsweise der Taschrechner von sinclair von 1973, alle 4 Grundrechenarten aus gerade 320 ROM-Worten: https://static.righto.com/calculator/sinclair_scientific_simulator.html
und ich frage mich heute noch wiese ein Mephisto Schachcomputer ohne gross RAM ein PC-Schachprogramm auf 4 Mbyte schlagen konnte.
Geht genauso, sofern die Befehle ein Byte–Stream sind, keine RISCs mit fester Befehlslänge. Nur die Implementierung stolpert u.U. über die eigenen Füsse und muss zeitraubend neu aufsetzen.
Disassembler ärgern kann man noch viel besser mit selbstmodifizierendem Code, das habe ich noch auf dem x86 gerne gemacht. Für Assembler auf dem Z80 oder 6502/10 bin ich zu jung.
Disassembler ärgern kann man noch viel besser mit selbstmodifizierendem
Code,
Damit konnte man allerdings auch die Implementierer von Prozessoren ganz
böse ärgern.
Naja, der Z80 oder 6502 hatten ja keinen Cache. Da konnte man sogar das Byte nach dem gerade verarbeiteten Opcode überschreiben.
Ich kann mich lebhaft an einen Fall auf den 6510 (aka C64) erinnern, wo der Code nur verschleiert war (EOR mit einem festen Byte). Ich habe da lange gegrübelt wie der Prozessor die Schleife verläßt um den Code anzuspringen. Dann fiel es mir wie Schuppen von den Augen: die EOR-Schleife schloß sich mit einem relativen Sprung und verwendete auch sonst selbstmodifizierenden Code um mehr als 256 Byte entschlüsseln zu können. Sie lief allerdings rückwärts durch den RAM. So hat sie dann irgendwann mal die Sprungdistanz des finalen BRAnches überschrieben. Und das war der Moment wo die Schleife endete :)
Ich kenne es nur vom Hörensagen, aber die Geschichte ist zu schön, um nicht erzählt zu werden.
Ein Kollege berichtete, daß sie früher auf der PDP (wahrscheinlich PDP-11) einen kleinen Trick gemacht hätten, um den doch begrenzten Speicher optimal zu nutzen.
In den Programmbefehlen gab es "ungenutze Bits", also solche, die für den Programmablauf nicht benötigt wurden. Hier konnte man Daten speichern - natürlich verteilt über mehrere Programmbefehle.
Also nicht nur selbstmodifizierender Code, sondern auch noch die Vermischung von Daten und Programm...
Was aber genial an der PDP war, ist die Tatsache, daß sie vollständig dokumentiert war. Ebenso die RS6000 von IBM. So habe ich damals ca. 30 Leitz-Ordner (es war natürlich eine andere Marke, die damals schon einen Plastikeinband hatten, der fürchterlich gestunken hat) "geerbt", in den massenweise Schaltpläne waren. Auch war jeder einzelne Befehl einzeln haarklein dokumentiert mit allen Auswirkungen.
Und nein, die gibt es nicht mehr. Nachdem sie noch ein paar Jahre im Serverraum herumstanden und ein Regal gefüllt haben, habe ich sie dann entsorgt.
In den Programmbefehlen gab es "ungenutze Bits", also solche, die für
den Programmablauf nicht benötigt wurden. Hier konnte man Daten
speichern - natürlich verteilt über mehrere Programmbefehle.
Also nicht nur selbstmodifizierender Code, sondern auch noch die
Vermischung von Daten und Programm...
Das ging auch beim Motorola 68000 Prozessor. Der hatte 24 Adressleitungen für 16 MB, die Adressregister und der Adressteil der Befehle war aber 32 bit lang. Also konnte man im oberen ungenutzten Byte andere Informationen ablegen, z.B. zur Speicherverwaltung.
Es gab damals so eine Computerfirma in Cupertino, die haben das ausgiebig genutzt. Da musste immer alles billig, billig sein, deshalb sollte das 68k-System mit satten 128k Speicher auskommen und jedes Byte war wertvoll. Später hat man dann gewaltig abgekotzt, um die Software "32 bit clean" zu bekommen, so dass man auch den Adressraum eines MC68030 jenseits der 16 MB ansprechen konnte.
Eine andere Variante, bestens geeignet um Disassembler zu ärgern, waren
Parameter direkt hinter einem Unterprogrammaufruf. Sowas wie
call stringcompare
db 'word' - letztes Byte mit Bit 7 gesetzt
Ich habe das sehr gerne beim 8051 gemacht. Es ärgerte mich, daß man in Assembler nicht einfach die Argumente dort hinschreiben kann, wo man sie im Ablauf brauchte. Die Texte und Daten standen also sonst wo, was das Lesen und Ändern erschwerte. Obendrein mußte man vor den Aufrufen ein Register mit der Adresse laden.
Beim 8051 geht das mit den Daten im Code sehr bequem, einfach den SP ins DPTR laden. Und am Ende nach DPTR springen. Der Keil C51 benutzt das z.B. bei switch/case.
In den Programmbefehlen gab es "ungenutze Bits", also solche, die für
den Programmablauf nicht benötigt wurden. Hier konnte man Daten
speichern - natürlich verteilt über mehrere Programmbefehle.
Braucht man dann nicht wieder immensen Programmcode um die Daten da rauszuziehen?
Stelle ich mir nicht sehr effektiv vor.
Wer beim Z80 mal noch ein einzelnes Bit braucht, kann das MSB im Refresh-Register verwenden...
Eine andere Variante, bestens geeignet um Disassembler zu ärgern, waren
Parameter direkt hinter einem Unterprogrammaufruf. Sowas wie
call stringcompare
db 'word' - letztes Byte mit Bit 7 gesetzt
Disassembler ärgern kann man noch viel besser
mit selbstmodifizierendem Code,
Damit konnte man allerdings auch die Implementierer
von Prozessoren ganz böse ärgern.
Ist korrekt, mindestens der 80486 merkt es nicht, wenn der Programmcode bereits in den Cache geladen ist. Aber genau das kann man auch super nutzen, um die böhsen Disassembler zu foppen. Man ruft über den DOS-Interrupt irgend eine bedeutungslose Funktion auf (z.B. AH=30h Get DOS Version) und ein paar Befehle vorher modifiziert man das MOV AH,30h in MOV AH,4ch (Terminate Program). Der 486er führt den INT 21h dann trotzdem mit AH=30h aus, im Debugger ändert sich der Code auf Terminate Program und sorgt zumindest kurz für ein Fragezeichen im Gehirn.
Funktioniert leider nicht mehr mit neueren Prozessoren, der Pentium merkt es bereits und lädt die Befehlswarteschlange neu (das Programm beendet sich dann auch ohne Debugger). Wenn der Effekt beim 486er stört, kann man nach dem Code modifizieren einen Sprungbefehl ausführen, dann lädt der 486er die Befehlswarteschlange auch neu.
Das waren noch Zeiten... Rumspielen mit den "Trace"-Interrupts, Teile des Programms im Bildschirmspeicher ausführen... dann kommt im Debugger Freude auf.
Das ging auch beim Motorola 68000 Prozessor. Der hatte 24
Adressleitungen für 16 MB, die Adressregister und der Adressteil der
Befehle war aber 32 bit lang. Also konnte man im oberen ungenutzten Byte
andere Informationen ablegen, z.B. zur Speicherverwaltung.
Es gab damals so eine Computerfirma in Cupertino
Microsoft hat das auch beim original Amiga-Basic so gemacht. Mit einem echten 32-Bitter lief das dann nicht mehr.
Das kenne ich nur vom 6502/10, bei dem "illegale Opcodes" eine Kombination aus mehreren Befehlen erlauben. Die meisten führen zum Absturz des Prozessors, aber viele sind wirklich sinnvoll nutzbar - und man könnte sagen, es ist sogar garantiert, daß sie auf jedem dieser Prozessoren funktionieren. Da findet man sehr viel in der C64-Ecke, wo solche Tricks regelmäßig benutzt wurden, ganz besonders in der Demo-Szene. Ich glaube, als Commodore das Ding damals entworfen und gebaut hat, war nicht mal denen klar, wozu diese Hardware fähig ist.
Welche Befehle soll es noch geben? Ich habe ein Buch über den U880, dort
ist im Befehlssatz keine Lücke.
Es handelt sich um die 2-Byte-Befehle bei denen das erste Byte DDh, EDh und FDh ist, da ist bei dem 2. Byte noch genug frei. Besonders bei den Indexbefehlen soll einiges gehen, aber ich habe mich damit noch nicht befasst.
Warum? Der U880 war viel besser …
… bei mir zu bekommen.
Es geht nicht um U880 vs Z80 sondern um die undokumentierten Instruktionen. Offensichtlich hast Du keinen einzigen Blick in jenes Dokument geworfen. Ich gebe zu, der Name ist etwas irreführend.
Herrliche Diskussion,da habe ich gleich mal mein Letztes Stück den LC80 eingeschaltet.
und er funktioniert noch....
War immer etwas schwieriger die Relativsprünge Fehlerfrei zu berechnen und einzugeben.
Dafür hatte ich unter Anderen eine Berechnungsroutine in einen Zusätzlichen E-Prom geschrieben.
Also, es heisst "undocumented" nicht "illeagl" und da dazu zählte man auch "zweckfreie" Befehle, die in ihrer Funktion zum NOP identisch waren.
Es ist halt so, das beim Auscodieren des Zustandsvector einer FSM auch Bit-kombinationen gibt, die im Betrieb nicht witklich entstehen. Bspw. kann man halt mit 4 FF 16 Zustände codieren, braucht weniger davon.
Dann codiert man die Zustände halt so, das man Logic per QuineMcClusky o.ä. optimieren kann.
Edit:
Ich les grad, beim x86 gibt es die Exception 6 wenn die Befehlseinheit auf einen Opcode stösst, dem kein Befehl zugeordnet werden kann. Ist halt kein Z80 und wird daher hier nicht vertieft.
Die schönste Form ist von Zuse überliefert: "The Z1 (1938) and Z3 (1941) computers built by Konrad Zuse contained illegal sequences of instructions which damaged the hardware if executed by accident."
https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)
Die schönste Form ist von Zuse überliefert: "The Z1 (1938) and Z3 (1941)
computers built by Konrad Zuse contained illegal sequences of
instructions which damaged the hardware if executed by accident."
https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)
Halt (Elektro-)Mechanik-Rechner, bei "112" kommt die Feuerwehr ;-)
Der U880 war dem Z80 funktional nachempfunden. Aber er war keine abfotografierte 1:1 Kopie, wie in der Journaille oft behauptet, sondern wurde an die vorhandenen Prozese angepasst neu implementiert. Einzelne Schaltungsteile weichen in der Umsetzung ab. Daher können die undokumenterten Funktionen des Z80 auch beim U880 vorhanden sein, sie müssen es aber nicht.
Im Osten wurden Programme oftmals mit ner Sprungtabelle
am Anfang des Programmes mit Sprüngen auf die einzelnen
Funktionen implementiert.
War das damals ne Ost-Mode oder war soetwas auch
in den gebrauchten Ländern üblich?
Das war üblich, und zwar für Funktionen, die auch von extern benutzt wurden. Der Sinn so einer Sprungtabelle war, für die externen Zugriffe einheitliche Einsprungadressen bereitzustellen, die sich auch dann nicht ändern, wenn die Funktionen mal neu geschrieben werden. So wie heutige APIs und DLLs.
Das machte man auch, wenn die einzelnen Teile des Programmes von verschiedenen Leuten geschrieben und später zusammengebaut wurden.
Wenn man es nicht so macht, kriegt man sowas wie das Monitor Programm vom AIM65, dessen API mitten ins ROM springt. Sowas wie Adresse E123 für Zeichenausgabe und FEDC für Druckfunktion. Bissel blöd, wenn man Fehler darin korrigiert. Weshalb sich an dessen Ende ein paar Flicken fanden, die von vorne angesprungen wurden und von dort wieder zurück sprangen, weil sich die Einsprungadressen nicht mehr ändern durften.
Ich bin deshalb auch Systemen begegnet, die solche Einsprünge als Sprungleiste vorneweg implementierten.
Im Osten wurden Programme oftmals mit ner Sprungtabelle
am Anfang des Programmes mit Sprüngen auf die einzelnen
Funktionen implementiert.
War das damals ne Ost-Mode oder war soetwas auch
in den gebrauchten Ländern üblich?
Das war üblich, und zwar für Funktionen, die auch von extern benutzt
wurden. Der Sinn so einer Sprungtabelle war, für die externen Zugriffe
einheitliche Einsprungadressen bereitzustellen, die sich auch dann nicht
ändern, wenn die Funktionen mal neu geschrieben werden. So wie heutige
APIs und DLLs.
Das machte man auch, wenn die einzelnen Teile des Programmes von
verschiedenen Leuten geschrieben und später zusammengebaut wurden.
Quasi ne Public-Schnittstelle?
Nicht schlecht!
Ich hab mich nur gewundert, das die Tabelle nie in den RAM
geschrieben wurde, was ja ne interruptähnliche Verwendung
ermöglicht hätte...
Da der Osten "gern" den Westen nachgebaut/kopiert hat ...
Und verbessert! Der 1057 von Robotron kam mit allen angeschlossen Geräten klar. Auf der Seite https://www.eser-ddr.de ist allerdings das Produktionsjahr des 1057 falsch, ich habe schon 1986/1987 an dieser Maschine das Fehlersuchen gelernt.
Da der Osten "gern" den Westen nachgebaut/kopiert hat ...
Und verbessert! Der 1057 von Robotron kam mit allen angeschlossen
Geräten klar. Auf der Seite https://www.eser-ddr.de ist allerdings das
Produktionsjahr des 1057 falsch, ich habe schon 1986/1987 an dieser
Maschine das Fehlersuchen gelernt.
Ja,
Die Drogenszene des Westens hat ja auch zu ihrer Finanzierung
genug Quellcode in den Osten geliefert, warum sollte er nicht darauf
aufbauen?!? :-P
Der U880 war dem Z80 funktional nachempfunden. Aber er war keine
abfotografierte 1:1 Kopie, wie in der Journaille oft behauptet, sondern
wurde an die vorhandenen Prozese angepasst neu implementiert. Einzelne
Schaltungsteile weichen in der Umsetzung ab.
Bspw. erinnere ich mich dunkel an unterschiedliches Verhalten der nM0 und nM1 Ausgangsleitungen bei IO-Zugriffen (nIOREQ = 'L'), was je nach Verdrahtung auf dem Board bei der Ansteuerung der Peripherieschaltkreise (PIO, CTC, ...) zu Problemen führen kann.
Und da Schaltungsteile (bspw. Register) als statische Speicher und nicht in dynamischer TransferGate Technologie gebaut waren, reagieren Z80 und seine Raubkopien unterschiedlich auf unterschiedliche Taktung bspw. Unter-Taktung. Und das auch noch gern Temperaturabhängig. Das Vermögen hohe kapazitiven Lasten bei langen leitungslängen/Fan-out zu treiben war auch unterschiedlich.
Und es gab beim Nachbau eigene Design-Entscheidungen, ob man erkannte "Logik-fehler" (gemeint sind wohl Diskrepanzen zum Z80-Datenblatt) ausmerzt oder im Sinne der Export-Eignung 1:1 nachbaut ("It's not a bug, it's a feature").
So hard-core-Optimieren haette ich selbst in meiner Jugendzeit nicht
gemacht, weil man den Code ein Jahr spaeter nicht mehr versteht.
Um Code auch nach längerer Zeit noch verstehen zu können, gab es auch damals schon die Möglichkeit für Kommentare. Selber Schuld, wer das bei solchen Tricksereien nicht nutzt.
Die Drogenszene des Westens hat ja auch zu ihrer Finanzierung
genug Quellcode in den Osten geliefert, warum sollte er nicht darauf
aufbauen?!? :-P
Geliefert ist gut, die haben dem KGB den offenen Minix-Quellcode verkaufen wollen - hat aber der KGB gemerkt. Oder einer der vom KGB in Sibirien verknackten Wissenschaftler.
Um Code auch nach längerer Zeit noch verstehen zu können, gab es auch
damals schon die Möglichkeit für Kommentare. Selber Schuld, wer das bei
solchen Tricksereien nicht nutzt.
Naja, bei 16kb Arbeitsspeicher bietet der Editor nicht viel Platz für
Kommentare neben den Mnemonics. Und was für den einen "Tricksereien",
das für den anderen fachspezifische Allgemeinbildung für die man eine
mehrjährige Ausbildung erfolgreich absolviert hat.
Und "dokumentiert" wurde/wird gern mündlich -"Wenn Du Fragen hast,
kannste gern bei mir vorbeikommen ..."
Die Drogenszene des Westens hat ja auch zu ihrer Finanzierung
genug Quellcode in den Osten geliefert, warum sollte er nicht darauf
aufbauen?!? :-P
Geliefert ist gut, die haben dem KGB den offenen Minix-Quellcode
verkaufen wollen - hat aber der KGB gemerkt. Oder einer der vom KGB in
Sibirien verknackten Wissenschaftler.
Naja, es gab auch noch mehr Leute als Hagbard Celline.
Und die haben sich besser angestellt. Immerhin hat
die Stasi die Telefongespräche über Scatting mitgehört,
und hatten auch die Hälfte der erpreßbaren Siemens-Mitarbeiter
unter Vertrag. ;-P
.... Und was für den einen "Tricksereien", das für den anderen
fachspezifische Allgemeinbildung für die man eine mehrjährige
Ausbildung erfolgreich absolviert hat.
Und "dokumentiert" wurde/wird gern mündlich -"Wenn Du Fragen hast,
kannste gern bei mir vorbeikommen ..."
Was spielt das für eine Rolle, wenn es um ein und die selbe Person geht?
Naja, bei 16kb Arbeitsspeicher bietet der Editor nicht viel Platz für
Kommentare neben den Mnemonics.
Es soll ja Gerüchten zufolge auch die Möglichkeit gegeben haben, Quelltext in sogenannten Dateien auf Dateisystemen abzuspeichern. Und die konnten dann auch größer werden als der dem Editor zugängliche Arbeitsspeicher. Sowas war dann in der Handhabung ungeschickt, weil der Editor bei Sprüngen im Quelltext immer wieder was nachladen musste, aber sowas konnte einem auch gleich beibringen, Programme modular zu gestalten, d.h. nicht alles in /ein/ ellenlanges Assemblerlisting zu stopfen.
Dabei konnten einem damals schon Programme wie Linker helfen.
Ok, wenn man das Pech hatte, an einem Computer zu arbeiten, der gar keine Dateien kannte (sondern nur Dinge auf Cassettenrecorder speichern konnte), dann hatte man natürlich die Arschkarte gezogen.
Mein allererster eigener Computer gehörte zu dieser Fraktion, allerdings hatte der keine 16 kByte Arbeitsspeicher, sondern effektiv nur eines, und das mit dem Kassettenrecorder war auch zum Abgewöhnen.
Der nächste, komplett selbstgebaute, hatte dafür zwei Diskettenlaufwerke und eine kombinierte RAM- und ROM-Disk, in letzterer landeten die meistbenutzen Programme (Editor, Assembler etc.), in ersterer lag der Kram, der gerade bearbeitet wurde -- ich durfte nur nicht vergessen, die Arbeit gelegentlich auf Disketten zu kopieren.
Der Arbeitsspeicher des Computers war 48 kB groß, die RAMdisk 256 kB und die ROMdisk auch. Um Graphik hat sich das angeschlossene Graphikterminal gekümmert (genauer, ein c't-Lötprojekt namens "Grip" http://www.prof80.de/files/grip1.pdf).
Später nutzte ich ein selbstgebautes Textterminal mit 96 Zeichen pro Zeile in 25 Zeilen (in einer 9x12-Pixelmatrix war das gerade noch auf einen BAS-Monitor verwendbar).
Allerdings: Der einzige Z80, der da überhaupt verwendet wurde, steckte im Graphikterminal.
Kann mich noch erinnern das mit dem LC80/U880/Z80 die nicht dokumentierten Befehle getestet werden konnte.
Auch ein bekannter Fehler des Z80 wurde mit dem U880 behoben.
War natürlich alles damals sehr mühselig.
Um Code auch nach längerer Zeit noch verstehen zu können, gab es auch
damals schon die Möglichkeit für Kommentare. Selber Schuld, wer das bei
solchen Tricksereien nicht nutzt.
Naja, bei 16kb Arbeitsspeicher bietet der Editor nicht viel Platz für
Kommentare neben den Mnemonics.
Textterminal mit 96 Zeichen pro
Zeile in 25 Zeilen (in einer 9x12-Pixelmatrix
Ne, da wird deine Erinnerung trügen.
Bei (Fernseh-) BAS und 15,625 kHz Zeilenfrequenz sind 768 x 576 Pixel darstellbar.
25 Zeilen ja, aber nur 60 oder 64 Zeichen pro Zeile, und kleiner Matrix.
Erst später gab es PC Bildschirme mit 31 kHz aufwärts.
ist euch auch schon mal aufgefallen das seit dem Ersten "PC" immer eine Programmiersprache mitgeliefert wurde,
Commodore Basic, apple basic, sinclair, pc1500, casio701, windows basic.....
Seit win 10/11 nichts mehr, die Leute sollen heute nur noch Programme kaufen und windows macht es einem sogar schwer alte Programmiersprachen zu installieren!
Textterminal mit 96 Zeichen pro
Zeile in 25 Zeilen (in einer 9x12-Pixelmatrix
Ne, da wird deine Erinnerung trügen.
Bei (Fernseh-) BAS und 15,625 kHz Zeilenfrequenz sind 768 x 576 Pixel
darstellbar.
25 Zeilen ja, aber nur 60 oder 64 Zeichen pro Zeile, und kleiner Matrix.
Gut dass Apple das nicht wusste. Bereits für den Apple IIplus von 1978 gab es eine "80 Zeichen-Karte", im wesentlichen ein Videoterminal mit MC6845. Das Ding lieferte 80 Zeichen mal 24 Zeilen. Kurze Zeit später kam die Videx Ultraterm mit 24x132, 32x128 und 48x80 Zeichen.
Natürlich brauchte man dafür einen vernünftigen BAS-Monitor mit 15, besser 18 MHz Analogbandbreite. Z.B. einen Apple Monitor /// oder einen AMDEK 200A. Mit einem NTSC-Fernseher mit 3 MHz Analogbandbreite war nicht viel zu holen, und mit einem CVBS-HDMI-Wandler mit 13,5 MHz Abtastrate ebensowenig.
ist euch auch schon mal aufgefallen das seit dem Ersten "PC" immer eine
Programmiersprache mitgeliefert wurde,
Die Programmiersprache war schon deshalb nötig, weil es zunächst ja kaum Programme gab. Damit man also einen Computer nutzen konnte, mußte man die Möglichkeit zur Programmierung haben.
Lange Zeit gaben die x86 beim Start die Fehlermeldung "no ROM Basic found" aus; wenn kein Bootdevice gefunden wurde, dann wurde nach einem ROM für den BASIC-Interpreter gesucht.
Gut dass Apple das nicht wusste. Bereits für den Apple IIplus von 1978
gab es eine "80 Zeichen-Karte"
ich erinnere mich noch gut an meinem Colormonitor der mit RGB Karte kam und den ich auf umschaltbar auf nur grün an die 80z Karte für CPMz80 anschließen konnte.
Taxan RGB Monitor und Colorgrafikkarte 1500,- DM zum Ende des Studiums ab 1985. Der Monitor syncronisierte auch die 18kHz der 80z Karte.
Ne, da wird deine Erinnerung trügen.
Bei (Fernseh-) BAS und 15,625 kHz Zeilenfrequenz sind 768 x 576 Pixel
darstellbar.
25 Zeilen ja, aber nur 60 oder 64 Zeichen pro Zeile, und kleiner Matrix.
Die Erinnerung trügt nicht. Das war eine 9x12-Matrix.
BAS-Monitor, nicht Fernseher. Und da ist die Horizontalauflösung nur vom Pixeltakt abhängig (und natürlich der Bandbreite des Videoverstärkers im Monitor).
Der Pixeltakt meines Selbstbauterminals betrug 16 MHz, damit ist ein Pixel 62.5 nsec lang; ein Zeichen also 562.5 nsec, und 96 davon brauchen 54 µsec.
Das passt mit Austastlücke und Co. problemlos in die 64 µsec, die sich aus der Zeilenfrequenz von 15.625 kHz ergeben.
Fernseher hatten nicht ansatzweise die nötige Videobandbreite, selbst Schwarzweißfernseher nicht. Die kamen wegen des Tonträgers auf etwas über 5 MHz.
Ich nutzte aber keinen Fernseher, sondern einen Monochrommonitor, und der hatte keine Probleme mit den 16 MHz.
Allerdings sind auch mit einem Monitor bei 15.625 kHz Zeilenfrequenz mehr als 300 Bildzeilen nur mit (meist unerträglichem, weil brutal flackerndem) Interlace möglich.
Das konnte mein Selbstbauterminal auch, dann hatte das Ding 50 Textzeilen, aber das war nur mit einem Monitor mit sehr lange nachleuchtendem Leuchtstoff erträglich.
So einen hatte ich, der wurde damals von Philips hergestellt und von Vobis unter dem "Highscreen"-Label vertrieben.
ist euch auch schon mal aufgefallen das seit dem Ersten "PC" immer eine
Programmiersprache mitgeliefert wurde,
Commodore Basic, apple basic, sinclair, pc1500, casio701, windows
basic.....
Seit win 10/11 nichts mehr, die Leute sollen heute nur noch Programme
kaufen und windows macht es einem sogar schwer alte Programmiersprachen
zu installieren!
Huch woher weißt Du das? ;-P
Ich hab gerad das Problem, den Borland jBuilder 7 auf
Win10 zu installieren, leider bricht das Installprogramm
kurz vor der Beendigung ab!
Ist das so, weil ich die 64 Bit Edition hab?
Muss ich da wirklich ne Win7 VM aufsetzen?
ist euch auch schon mal aufgefallen das seit dem Ersten "PC" immer eine
Programmiersprache mitgeliefert wurde,
Die Programmiersprache war schon deshalb nötig, weil es zunächst ja kaum
Programme gab. Damit man also einen Computer nutzen konnte, mußte man
die Möglichkeit zur Programmierung haben.
Bei der SUN hat man (als administrator) auch ab und zu den kernel oder Teile davon kompilieren müßen bspw. bei Hinzufügung neuer Hardware/Filesystem.
OK, SUN kam ja auch aus dem Universitären Bereich und wurde technisch gesehen von einem deutschen Hacker voran getrieben. Der hatte "Mach es selbst oder lass es sein" verinnerlicht. Und gehört nicht cc spätetestens seit 1990 zum Unix (POSIX)-Mindestumfang ?!
Ach so, der TO spricht von PC's und nicht von workstations ;-) .
Disassembler ärgern kann man noch viel besser mit selbstmodifizierendem
Code,
Damit konnte man allerdings auch die Implementierer von Prozessoren ganz
böse ärgern.
Es sei denn Implementierer wie dieser Seymour Cray wollten das so. Ich meine, wir hatten ja nix. Gar nix! Wir hatten nicht mal einen Return-Stack in unserem alternden Super-Computer https://en.wikipedia.org/wiki/CDC_7600
Ein Unterprogramm aufrufen? Ok, erste Aktion im Unterprogramm war die Herkunftsadresse in eine Rücksprungadresse umwandeln. Damit modifizierte sich das Unterprogramm selber in dem es einen Sprung zur Rücksprungadresse ans eigene Ende schrieb.
Das war der offizielle Weg. Das funktionierte auch - meist. Aufgrund der Architektur konnten sich keine zwei Aufrufe in die Quere kommen. Es sei denn man versuchte sich an so neumodischem Kram wie Rekursion. Wobei der Maschine selbstverständlich egal war ob man es mit einer direkten oder indirekten Rekursion versuchte.
Ich les grad, beim x86 gibt es die Exception 6 wenn die
Befehlseinheit auf einen Opcode stösst, dem kein Befehl
zugeordnet werden kann.
Der x86 schmeißt Dir einen Software-Interrupt, heißt direkt "illegal opcode". Das hat man früher auch gebraucht, weil es z.B. viele CPUs gab, die keine FPU enthielten (386SX/486SX, die mit FPU hießen DX). Wenn man auf denen Code ausführen wollte, der z.B. für Fließkomma-Berechnungen die FPU benutzt, dann crasht der auf solchen CPUs. Wenn man sich vorher diesen Interrupt geschnappt hat, konnte man wenigstens noch eine Fehlermeldung ausgeben und das Programm crashfrei beenden - oder wenn man sich die Mühe gemacht hat, Code ohne FPU-Befehle benutzen.
Ich les grad, beim x86 gibt es die Exception 6 wenn die
Befehlseinheit auf einen Opcode stösst, dem kein Befehl
zugeordnet werden kann.
Der x86 schmeißt Dir einen Software-Interrupt, heißt direkt "illegal
opcode". Das hat man früher auch gebraucht, weil es z.B. viele CPUs gab,
die keine FPU enthielten (386SX/486SX, die mit FPU hießen DX). Wenn man
auf denen Code ausführen wollte, der z.B. für Fließkomma-Berechnungen
die FPU benutzt, dann crasht der auf solchen CPUs. Wenn man sich vorher
diesen Interrupt geschnappt hat, konnte man wenigstens noch eine
Fehlermeldung ausgeben und das Programm crashfrei beenden - oder wenn
man sich die Mühe gemacht hat, Code ohne FPU-Befehle benutzen.
Was man beim Amiga (und vermutlich nicht nur dort) auch gemacht hat.
Ohne FPU gab es eine entsprechende Exception wodurch dann per IRQ die Fließkommaberechnung in Software durchgeführt wurde.
Für die Software kein Unterschied, ob FPU vorhanden oder nicht.
Genau. Beim 80386 gab es beim Versuch, bei Abwesenheit einer FPU eine FPU-Instruktion auszuführen, eine Device Not Available Exception. Also eine andere Exception als bei wirklich undefinierten Instruktionen.
Ist korrekt, mindestens der 80486 merkt es nicht, wenn der Programmcode
bereits in den Cache geladen ist.
Und eine frühe Version eines Prozessors aus der AMD K6 Familie erkannte ab und zu auf self modifying code, obwohl es keiner war, und führte dann u.U. einen Befehl zweimal aus.
Ohne FPU gab es eine entsprechende Exception wodurch dann per
IRQ die Fließkommaberechnung in Software durchgeführt wurde.
Für die Software kein Unterschied, ob FPU vorhanden oder nicht.
Tricky... habe ich aber nie gebraucht, zumindest nicht für sinnvolle Dinge.
Meine DOS-Testviren, mit deren hochprofessioneller Entwicklung und Perfektionierung ich damals meine Freizeit verschwendet habe, waren komplett für 32 Bit geschrieben und enthielten einen entsprechenden Test falls sie doch mal auf einem 286er gestartet werden würden. Die gab es damals vereinzelt noch. Dann wäre immerhin das infizierte Programm selbst noch gelaufen, nur eben der Virus nicht.
Ich les grad, beim x86 gibt es die Exception 6 wenn die
Befehlseinheit auf einen Opcode stösst, dem kein Befehl
zugeordnet werden kann.
Der x86 schmeißt Dir einen Software-Interrupt, heißt direkt "illegal
opcode". Das hat man früher auch gebraucht, weil es z.B. viele CPUs gab,
die keine FPU enthielten (386SX/486SX, die mit FPU hießen DX). Wenn man
auf denen Code ausführen wollte, der z.B. für Fließkomma-Berechnungen
die FPU benutzt, dann crasht der auf solchen CPUs. Wenn man sich vorher
diesen Interrupt geschnappt hat, konnte man wenigstens noch eine
Fehlermeldung ausgeben und das Programm crashfrei beenden - oder wenn
man sich die Mühe gemacht hat, Code ohne FPU-Befehle benutzen.
Für all die Rechner, denen die FPU fehlte, gab es speicherresistente Emulatoren. Die haben sich eben diesen Interrupt gegriffen und die entsprechenden Befehle emuliert. War schnarchelangsam, aber notwendig, wollte man z.B. mit AutoCAD arbeiten. Z.B. https://www.qnx.com/developers/docs/qnx_4.25_docs/qnx4/utils/e/emu87.html
ist euch auch schon mal aufgefallen das seit dem Ersten "PC" immer eine
Programmiersprache mitgeliefert wurde,
Commodore Basic, apple basic, sinclair, pc1500, casio701, windows
basic.....
Seit win 10/11 nichts mehr, die Leute sollen heute nur noch Programme
kaufen und windows macht es einem sogar schwer alte Programmiersprachen
zu installieren!
Dann schau Dir mal Deine Handtelefoniereinrichtung an. Bis Du da drauf eigenen Code laufen lassen kannst, hast Du eher den C64 im Keller wieder gefunden.
Disassembler ärgern kann man noch viel besser mit selbstmodifizierendem
Code, das habe ich noch auf dem x86 gerne gemacht. Für Assembler auf dem
Z80 oder 6502/10 bin ich zu jung.
Sowas habe ich oft gefunden, wenn ich zu MS-DOS-Zeiten Viren disassembliert habe. Die haben ihren "weitergetragenen" Code gerne nicht nur zu 95% mit XOR-Bearbeitung in einer Schleife verschleiert, sondern auch diese Schleife mit ständig wechselnden Registern / Offsets / Richtung der Bearbeitung ausgeführt. Da sah der Code nie gleich aus - das sollte Antivirus-Programme verwirren.