Hier auf der Suche nach dem Default-Bitmap des Amigas des Desktops
Archiv der Kategorie: Assembler
move.l: Verschieben oder Kopieren?
Der Move-Befehl ‚verschiebt‘ einen Wert von A nach B – so sagt es zumindest das Naming. Eigentlich verschiebt er den Wert nicht nur, sondern er kopiert ihn. Aber selbstverständlich wird er damit auch ‚verschoben‘. Es wäre auch eine gute Frage, falls er ihn ‚verschieben‘ würde, was an dessen Stelle wäre am alten Ort. Das wäre ja ein ‚echtes‘ Verschieben.
„Wo zur Hölle schreibt das im Speicher rum?“ (Anonymer Entwickler)
Das grosse Meer der Speicher.
WeiterlesenVon 8Bit zu 16Bit (nur Assembler)
- mehr dafür logischere Befehle und Naming (vgl inc und add.l #1)
Bsp: Logische benennung bei BGT, LT etc. - keine 256er Grenze mehr (kein Abfragen bei 255+10 mehr) – Überlauf
- viel weniger Speedprobleme
- eine For-Next-Schleife (dbra)
- keine Angst mehr vor: Code ist zu lang, kann nicht mehr kompiliert werden
- …
Das Dev-Puzzle
Was zur Hölle funktioniert jetzt gerade nicht mehr. Ich arbeite am DoubleBufferedUpdaten der Tiles.
Der neue digitale Raum und seine Szenen (GameDev, Cracker, Demoscene …) [wird upgedated]
Eine der interessantesten Fragen zur Homecomputerzeit und ihren Bewegungen ist sicherlich der teilweise gemeinsame Ursprung verschiedenster Szenen und die Ausdifferenzierung danach in verschiedenste Felder. Es stellt sich sogar die Frage, ob diese Ausdifferenzierung auch zur Differenzierung gegenüber anderen Bereichen geführt hat.
Versuch einer Einschätzung:
Category | Business | GameDesign | Crackerscene | Demoscene | Virendevscene | Art/MediaArt |
produkt | apps | games | crackerintros, trainer | demos | viren | kunst |
soz. produkt | firmen | comm. / firmen | crackergroups, metachallenge/game | demogruppen, metachallenge | ||
öffentlich | +++ | +++“ | +/- | +/- | – | + |
intern. öffentlichkeit | ++ | +++ | ++ (handles) | +++ (handles) | ? | |
visuell | gui | +++ | + | +++ | – | |
art visuell | anal. vorbilder | anal/abstract | +- abstract | – | ||
auditiv | – | +++ | +++ | – | + | |
interaktiv | + | +++ | – (trainer) | – | – | + |
coding | + | +++ | ++ | +++ | +++ | + |
unterhaltung | – | +++ | – | +++ | +/- | |
art unterhaltung | interakt. | interakt. spiele | linear | linear | – | |
scene (motivation) | markt | markt/challenge | „markt“/challenge | challenge | challenge | |
kompensation | geld | geld/ruhm, (symbl.) | symbolisches kapital, scene (geld) | symbolisches kapital, scene | symbolisches kapital, spass | |
quereffekte/learnings (findings) | coding, technologie lernen | coding lernen, reverse ingenieering | coding lernen, tricks | gefährlich, ungeliebt |
// ToDo: klare Trennung – Scene – Produzent – Produkt – Consumer
// ToDo: Add costs
Assembler: jmp (jump)
Und man* tut es einfach: Man benützt den Jump-Befehl und springt irgendwo hin und macht da weiter – irgendwo im immer linearen Code. Hinein in die psychische Konstruktion des Code (und seinen Hierachien), die am Ende linear ist.
Es ist letztlich Anarchie, die immer noch Assembler als Option hat und die Lust daran. Es ist der Möglichkeitsraum, Dinge zu tun, die man eigentlich nicht mehr tut in den höheren Programmiersparchen. Wo man Dinge konstruiert in Verschachtelungen, in Hierarchien, die nicht überspringbar sind. Code also der letztlich, wie die Systemtheorie funktioniert. Systeme in Systemen – aber brich niemals aus! Dadurch ist auch hochintegrierter Code möglich. Letztlich nachhaltiger Code.
Es ist die Freiheit und Bürde von Assembler zugleich (Hängt da mein Code wieder in einer Endlosschleife?). In diesem Fall springt der Code „jmp next_level“ (ich springe, geistig beim Nachprüfen) über alle Hierarchien zum Code für den nächsten Level (nach oben). Kein Gequäle ist das durch die Hierarchien der Verschachtelungen mit {} – sondern einfach da hoch.
Eine Erfahrung die ab 1964 viele natürlich mit GoTo gemacht haben.
Anarchie muss ab und zu sein.
Ausstellung: Erfahrbarmachung von Assembler – Setzkasten
Ein Erfahrbarmachung, wie funktionieren Programmiersprachen in ihrer Komplexität wäre vielleicht mit einem Setzkasten und eine einfache Programmieraufgabe. Darin sieht man schnell wie sehr einschränkend etwa ein 6502 (oder weniger 6800) waren im Gegensatz zu einem 68000.
// ToDo: Nutzung von HumanRessources als Spiel dazu oder dann die DSP-Games
Hier das Puzzle zusammengesetzt für eine PrintNumber Routine
Copy&Paste in Assembler – no go
Was in heutigen Programmiersprachen gang und gäbe ist, die Technik Dinge von X nach Y zu kopieren und dort anzupassen, ist in Assembler nicht so einfach möglich. Der Grund: In heutigen Programmiersprachen gibt es keine Sprungmarken mehr, diese müssen aber mühsam angepasst werden Assembler. Es darf ja (ausser bei modernen relativ adressierbaren Assembler) keine zwei gleichlautende Sprungmarken geben. Anders gesagt: Copy&Paste ja, aber zu einem Preis: Generierung von vielen neuen Labels und damit auch jede Menge möglicher Fehler und viel Neu-Testing.
Und dies trifft Videogames besonders, da Videogames geradezu von Bedingungen leben (ifs, loops etc).
Gridrunner (Jeff Minter) – 68000 ATARI ST Assembler:
// {} vs a: b:
// Mehr Subroutinen in Assembler > Frage an die Entwickler
// Vgl dazu die Demoscene
Assembler (inklusive Basic, Tutor?) vs moderne strukturierte Programmiersprachen (C, Pascal, C++, Pascal, Brainfuck) [In Bearbeitung]
Wer Assembler programmiert (oder auch Basic mit Goto Zeilennummern/Sprungmarkenmöglichkeiten) stellt schnell fest, hier kann man viel mehr machen als in modernen strukturierten Programmiersprachen (mit derselben Anzahl von Zeichen). Moderne strukturierte Programmiersprachen ähneln mehr einem modernen Rezept, während unstrukturierte eher einem Hypertext ähneln.
Moderne strukturierte Programmiersprachen und ihr Baumkonzept
Moderne (strukturierte) Programmiersprachen und ihre Ablaufdiagramme sind eine Teilemenge (nicht eigentlich) der viel grösseren Menge der Maschinensprachen mit ihren JMP und GOTO Befehlen. Der Code springt in Unterroutinen und kehrt dann wieder zurück in den nächst höheren Prozess.
Dadurch entsteht eine Art Baum und wie bei Treestrukturen üblich, ist es jederzeit klar, wo sich der Programmpointer(‚man‘) befindet. Jeder Punkt ist klar definiert, weil der Rückweg immer klar ist – den Tree up. Je tiefer der Tree ist, umso grösser die Verwaltungsaufgabe, schliesslich muss man sich immer merken, wie man zurückkommt.
Prinzipiell hat C. Böhm ( https://en.wikipedia.org/wiki/Corrado_Böhm ) früh – 1963 – gezeigt, dass sich alle unstrukturierten Programmiersprachen in strukturierte überführen lassen. Er hat dazu eine theoretische Programmiersprache entwickelt mit sehr wenigen Befehlen. Eine wiedererfundene Version dafür kennt man heute Brainfuck von U. Müller, das nur von den Befehlen +-[] etc lebt. Diese Sprache hat natürlich einen Preis, die Source-Codes sind riesig.
Der Vorteil ist sofort klar: Lesbarere Strukturen (Trennung zwischen Fakten und Regeln klar), da es klare Ablaufdiagramme gibt.
An verschiedenen Stellen (raussuchen) wird darauf hingewiesen, dass gerade 8Bitter wegen RAM (auch in Sachen Tools) und kleinem Stack nicht in der Lage sind wirklich höhere strukturierte Programmiersprachen zu bieten. Es fällt auch auf, dass es wenige strukturierte Programmiersprachen gibt auf diesen Systemen und viele erst heute nachträglich entwickelt werden, um zu zeigen, dass es doch funktioniert.
// ToDo: Checken der These, dass es bei 8Bit-Homcomputern wenige Compiler und Hochsprachen gibt, weil das RAM fehlte bzw. die Stacks zu klein waren für gute Compiler.
// Trees sind deswegen bekanntlich sehr beliebt, da sie machttechnisch grösstmögliche Kontrolle erlauben. Natürlich lassen sich damit nur eine beschränkte Datenstruktur oder auch Prozessstruktur abbilden – aber für viele Systeme reicht es (oder eher muss es reichen).
Unstrukturierte Programmiersprachen – willkommen in rhizomatischer Ausführung
Assembler dagegen ist das potentiell offen in der Struktur. Es kann kreuz und quer Daten uns Code verteilt werden (nicht der beste Stil) – letztlich besteht darin auch kein Unterschied – das eine sind ausführbare Daten, das andere interpretierte Daten – aus Sicht des Programs.
Prinzipiell gibt es wenige Befehle. LDA (load A), STA (store A), CMP, JMP. Dadurch entstehen logisch stringente Programme. Ebenso ist das Rechenwerk meist sehr eingeschränkt (etwa beim billigen 6502): Register A,X,Y. All dies macht die Programm lang und oft schwer lesbar.
Als Flaschenhals kommt hinzu, dass viele Operationen nicht im allgemeinen (langsamen) RAM ausgeführt werden können, sondern nur im ‚Rechenwerk‘ und darum dahinein geladen werden müssen bsp. lda #1 (Lade 1 ins A-Register).
Der wichtigste Unterschied zu strukturierten Programmiersprache ist aber sicherlich die Möglichkeit des „Springens“ JMP (oder GOTO) und alle Flag-Abhängigen-Sprünge aus „Compares wie CMP“ wie BEQ (gleich), BNE (ungleich), BCC (kleiner als), BCS (grösser als) etc.
Ein fiktives Beispiel:
lda #10
ohje:
clc
adc #1
clc // clean the state-register
cmp #4
beq it_is_four // same
bne it_is_notfour // not the same
it_is_four:
jmp end_of_all
it_is_notfour:
jmp oh_je
end_of_all:
Dies ermöglicht dann alle möglichen Versionen von Ausführungen. Komplizierter wird das Ganze dann auch noch, wenn sich der Source-Code über mehrere Seiten erstreckt. Und selbstverständlich lassen sich Dinge in Unterroutinen verpacken, das Problem allerdings dann da: Handling der Parameter (auf den kleinen Stack oder in eigene Variablen?).
Im konkreten Programmierprozess müssen durch die Sprungmarken auch immer wieder neue Sprungmarken gefunden werden. Dies ist bei weitem aufwändiger als etwa in C. Die Haupbenennungsaufgaben sind quantitativ die Variablen/Members und die Methoden.
Die Variablen sind ähnlich aufwändig in Assembler:
a: .byte 0
vs
byte a = 0;
Dasselbe gilt für die Funktionen/Methoden:
render_me:
[...]
rts
vs
void render_me() {
}
Viel aufwändiger wird es hingegen bei jeder kleine If-Abfrage bzw. in Sachen fornext (was ja eine verkürzte Schreibweise ist C). Hier müssen immer wieder neue Sprungmarkennamen gefunden werden (auch wenn moderne Assembler hier auch lokale relative Namings ermöglichen).
ldx #10
count_down:
clc
cpx #4
is_not4
is_not4:
inx
clc
cmp #0
bne count_down
vs
for (int i=0;i<10;i++) {
if (i==4) {
}
}
Selbstverständlich klingt, das im ersten Moment nicht nach viel. Das Problem potentiert sich aber dann mit jeder neuen Abfrage und jeder ForNext-Schleife.