Zum Inhalt springen
AetherOS und die zehn Apps werden noch gebaut. Zu haben sind bisher nur Schriften, Emojis und Farben – Apps geplant für Sommer 2027. Was noch kommt
AetherOS

Programmieren mit .ae

Die eigene Sprache von AetherOS hat deutsche Befehle. Diese Seite zeigt die Grundlagen – Schritt für Schritt, mit echter Schreibweise aus dem Compiler. Jeder Befehl, der hier vorkommt, steht in der Liste der 22 Schlüsselwörter in lexer.js – nur und und oder liest er als Rechenzeichen; wo der Übersetzer für den Kernel etwas noch nicht kann, steht es direkt dabei.

Zum Lesen, noch nicht zum Ausprobieren. .ae läuft heute nur im eigenen Kernel von AetherOS, nicht im Browser. Die Beispiele zeigen die Schreibweise, die der Compiler versteht. Am Quelltext des Compilers nachgeprüft am 27. September 2026.

1 · Kommentare

Alles hinter // ist eine Notiz für Menschen. Der Compiler überliest es bis zum Ende der Zeile. Ein Kommentar darf auch hinter einer Anweisung stehen, wie im Beispiel auf der Sprachseite. Im Kernel erklären Kommentare oft Zahlen, die man sonst nachschlagen müsste – etwa „KBC Reset-Befehl an Port 0x64“ hinter einem Neustart-Befehl.

// Das ist ein Kommentar

2 · Werte merken

variabel legt einen Wert an, der sich ändern darf. fest legt einen Wert an, der gleich bleibt. Beide brauchen sofort einen Anfangswert hinter dem Gleichheitszeichen. Namen dürfen Umlaute und ß enthalten, Ziffern aber erst ab der zweiten Stelle – ein Name wie 2te geht nicht, zweite2 schon. Feste Werte schreibt der Kernel groß, damit man sie auf einen Blick erkennt – alle 132, gezählt am 27. September 2026. Der Compiler verlangt das nicht, es ist Absprache.

fest MAXIMUM = 10
variabel zähler = 0
zähler = zähler + 1

3 · Rechnen und vergleichen

Gerechnet wird mit + - * / %, verglichen mit == != < > <= >=. Für einzelne Bits gibt es & | ^ ~ << >>. Bedingungen verbindet man mit und und oder. Zahlen dürfen auch hexadezimal stehen, etwa 0xB8000. % liefert den Rest einer Teilung, & mit 255 behält nur das unterste Byte – beides braucht der Kernel ständig, wenn er Zahlen für den Bildschirm zerlegt. Geteilt wird ganzzahlig: 17 / 5 ergibt 3, der Rest 2 geht verloren.

variabel fläche = breite * höhe
variabel rest = 17 % 5
variabel unten = wert & 255

Im Kernel sind Zahlen 16 Bit groß: von 0 bis 65.535. Was darüber hinausgeht, fängt wieder unten an. Vergleiche rechnen dabei mit Vorzeichen: Ab 32.768 gilt eine Zahl in < und > als negativ und damit als kleiner als 1. Große Adressen besser nicht mit < prüfen – mehr dazu auf der Sprachseite.

4 · Entscheiden

wenn prüft eine Bedingung, sonst sagt, was andernfalls passiert, ende schließt ab. Ein ende gehört immer zum ganzen Block, auch wenn es einen sonst-Teil gibt – es sind also nie zwei. Die Einrückung ist nur für Menschen da; der Compiler schaut allein auf die Wörter.

wenn zähler >= MAXIMUM
    zähler = 0
sonst
    zähler = zähler + 1
ende

Zeilenumbrüche zählen nicht: Der Lexer wirft sie weg und merkt sich nur die Zeilennummer für Fehlermeldungen. Deshalb darf ein ganzer Block auch in einer Zeile stehen. Diese Zeile steht genau so am Anfang des Kernels – sie sorgt dafür, dass er nur einmal startet:

wenn kernel_booted == 1 rueckgabe 0 ende

Vorsicht mit und und oder: Der Übersetzer für den Kernel prüft verknüpfte Bedingungen bisher nicht – der Teil dahinter läuft dann immer. Sicher ist heute ein wenn im wenn, je mit einem einzelnen Vergleich. Im Kernel betrifft das 130 von 1.193 Bedingungen, gezählt am 23. September 2026 – ein bekannter Fehler, kein Stil. Warum das so ist

5 · Wiederholen

solange wiederholt, solange eine Bedingung stimmt. Geprüft wird vor jedem Durchgang – stimmt sie schon am Anfang nicht, läuft der Rumpf kein einziges Mal. wiederhole … mal wiederholt eine feste Anzahl. Es liest sich leichter, doch der Übersetzer für den Kernel kann es noch nicht; dort zählt man mit solange und einer eigenen Variable, wie im ersten Beispiel.

variabel i = 0
solange i < 10
    i = i + 1
ende

wiederhole 3 mal
    zähler = zähler + 1
ende

6 · Funktionen

funktion gibt einem Stück Code einen Namen. rueckgabe liefert ein Ergebnis zurück – dahinter muss immer ein Wert stehen, ein leeres rueckgabe kennt der Parser nicht. Mehrere Werte in der Klammer trennt ein Komma. Im Kernel liegen die Werte einer Funktion an festen Stellen im Speicher: Eine Funktion, die sich selbst aufruft, würde ihre eigenen Werte überschreiben.

funktion quadrat(zahl)
    rueckgabe zahl * zahl
ende

variabel neun = quadrat(3)

7 · Andere Dateien einbinden

lade bindet eine andere .ae-Datei ein – so teilt sich der Kernel auf viele Dateien auf. Der Name steht in Anführungszeichen und gilt vom Ordner der ladenden Datei aus. Jede Datei kommt nur einmal hinein, auch wenn sie mehrfach geladen wird. So bleibt jede der 64 .ae-Dateien im Kernel-Ordner unter der 300-Zeilen-Grenze des Regelwerks; die längste hat am 27. September 2026 298 Zeilen.

lade "kernel_string.ae"

8 · Nah an der Hardware

Zeiger

zeiger zeigt auf eine Adresse im Speicher. So schreibt der Kernel zum Beispiel direkt in den Bildschirmspeicher. Mit eckigen Klammern wählt man eine Stelle dahinter, etwa vga[index * 2]. Unterhalb der Adresse 1024 lässt der Übersetzer nichts schreiben – dort liegt die Tabelle für Unterbrechungen.

Ports

Mit eigenen Befehlen lassen sich Hardware-Ports lesen und beschreiben: lese_port und schreibe_port für 8 Bit, dazu je eine Fassung mit 16 am Ende. Über Ports fragt der Kernel die Tastatur ab, liest die Uhr und schaltet den Lautsprecher.

Maschinencode

asm bettet Befehle für den Prozessor direkt ein – nur für Fortgeschrittene. Der Befehl steht als Text dahinter, etwa asm "cli". Rund 80 Befehle kennt der Übersetzer beim Namen; ein Tippfehler darin fällt ohne Warnung weg.

Diese Befehle braucht ein Betriebssystem, weil unter ihm niemand mehr ist, der die Arbeit mit der Hardware abnimmt. Für die ersten Schritte sind sie nicht nötig.

9 · Auf den Bildschirm schreiben

text_setzen schreibt einen Text an eine Stelle des Bildschirms. Die Reihenfolge ist Spalte, Zeile, Text, Farbe. zahl_setzen macht dasselbe mit einer Zahl. Beide schreiben direkt in den Textbildschirm – es gibt kein Fenster und keine Konsole dazwischen, die mitscrollt. Was an einer Stelle stand, wird einfach überschrieben.

fest WEISS = 15
fest GELB = 14
text_setzen(0, 0, "Hallo Aerona", WEISS)
zahl_setzen(0, 1, zähler, GELB)
  • Der Bildschirm hat 80 Spalten und 25 Zeilen, gezählt wird ab 0. Liegt die Stelle außerhalb, wird nichts geschrieben.
  • Der Text muss direkt in Anführungszeichen stehen. Eine Variable ist an dieser Stelle nicht erlaubt – der Parser verlangt hier ausdrücklich einen Text und meldet sonst „Erwartet TEXT …, aber fand …“.
  • Die Farbe ist ein Byte: Hintergrund mal 16 plus Schrift. Die 16 Farben heißen im Kernel COLOR_BLACK (0) bis COLOR_WHITE (15) – 1 ist Blau, 4 Rot, 14 Gelb. 15 ist also Weiß auf Schwarz, und 112 (7 × 16) ist Schwarz auf Hellgrau: So zeichnet der Kernel seine Uhr.
  • Der x86-Übersetzer zeigt von der Zahl das unterste Byte als zwei hexadezimale Ziffern: Aus 26 wird 1A.

10 · Die Reihenfolge beim Rechnen

Zuerst rechnet der Compiler *, / und %. Alles andere liest er streng von links nach rechts – auch Vergleiche, und und oder. Das ist anders als in den meisten Sprachen, in denen ein Vergleich erst nach dem Rechnen kommt. Der Parser kennt nur diese zwei Stufen, nachzulesen am Anfang von parser-expr.js; auch die Bit-Zeichen &, | und << stehen auf der unteren.

// wird gelesen als (a == b) - 1
wenn a == b - 1
    a = 0
ende

// so ist es eindeutig
wenn a == (b - 1)
    a = 0
ende

Im Zweifel Klammern setzen. Sie machen die Absicht klar und erzeugen keinen zusätzlichen Code. Das Beispiel oben baut der Compiler ohne Meldung – der Fehler zeigt sich erst beim Laufen.

11 · Wenn der Compiler sich meldet

Findet der Compiler einen Fehler, bricht er ab und nennt meist die Zeile. Lexer und Parser kennen vier Meldungen. Eine Vorsicht vorweg: Die Zeilennummer zählt im zusammengesetzten Text, nachdem alle lade-Anweisungen aufgelöst sind – beim Kernel ist das nicht die Zeile in der einzelnen Datei. Und das Bauskript bauen.bat schreibt am Ende immer „FERTIG!“, auch nach einem Fehler; die Meldung steht in den Zeilen darüber.

Meldungwas sie meist bedeutet
Unbekanntes ZeichenIm Quelltext steht ein Zeichen, das .ae nicht kennt – etwa ein Semikolon oder ein Punkt.
Unerwarteter BefehlWo eine Anweisung beginnen müsste, steht etwas anderes.
Erwarte FaktorAn dieser Stelle fehlt ein Wert, zum Beispiel nach einem Rechenzeichen.
Erwartet …, aber fand …Ein bestimmtes Wort oder Zeichen fehlt, etwa eine Klammer. Steht dort „Dateiende“, fehlt oft ein ende.

Dazu kommen drei Meldungen außerhalb von Lexer und Parser:

  • „Konnte die Datei … nicht finden“ – die Startdatei fehlt.
  • „Enthaltene Datei … existiert nicht“ – eine lade-Anweisung zeigt ins Leere.
  • „Code-Bereich überschneidet sich mit String-Bereich“ – das Programm ist zu groß geworden: Der Code wächst von vorn, die Texte von hinten, und irgendwo stoßen sie zusammen. Die Meldung nennt die Funktion, in der es passiert ist.

12 · Ein echtes Stück Kernel, Zeile für Zeile

Alles bisher Gezeigte steckt in dieser Funktion aus kernel_main.ae. Sie schreibt auf den Bildschirm, wie viel Speicher der Buddy-Verwalter in jeder seiner fünf Größenstufen noch frei hat – wörtlich aus dem Kernel:

funktion print_buddy_lists()
    variabel o = 0
    solange o <= 4
        variabel val = buddy_get_free_list(o)
        text_setzen(0, 12 + o, "ORDER ", 15)
        zahl_setzen(6, 12 + o, o, 15)
        text_setzen(8, 12 + o, ": ", 15)
        zahl_setzen(10, 12 + o, val / 256, 15)
        zahl_setzen(12, 12 + o, val & 255, 15)
        o = o + 1
    ende
ende
  1. Zählen. o läuft von 0 bis 4 – eine Zeile je Größenstufe.
  2. Fragen. buddy_get_free_list(o) liefert, was in dieser Stufe frei ist.
  3. Hinschreiben. Ab Zeile 12 des Bildschirms, jede Stufe eine Zeile tiefer, in Weiß (15).
  4. Zerlegen. zahl_setzen zeigt nur ein Byte als zwei Ziffern. Deshalb schreibt die Funktion die obere Hälfte (val / 256) und daneben die untere (val & 255) – zusammen vier Ziffern für eine 16-Bit-Zahl.

13 · Was es noch nicht gibt

  • Nur ganze Zahlen: Einen Punkt wie in 3.5 kennt der Compiler nicht. Der Lexer bricht beim Punkt mit „Unbekanntes Zeichen“ ab.
  • Ein Anführungszeichen innerhalb eines Textes geht nicht – der Text endet dort. Einen Ausweg wie \" gibt es nicht; umgekehrt läuft ein vergessenes schließendes Zeichen bis zum nächsten Anführungszeichen weiter, auch über Zeilen hinweg.
  • Kommentare gibt es nur mit //, für jede Zeile einzeln. Einen längeren Abschnitt stilllegen heißt also, vor jede Zeile zwei Schrägstriche zu setzen.
  • Ruft man eine Funktion, die es nicht gibt, meldet der Übersetzer für den Kernel keinen Fehler: Es passiert schlicht nichts, und in einer Rechnung steht an ihrer Stelle 0.
  • Ein zeiger liest und schreibt immer genau ein Byte. Für eine 16-Bit-Zahl braucht es deshalb zwei Zugriffe, wie beim Zerlegen im Beispiel oben.
  • wiederhole … mal versteht der Parser. Der x86-Übersetzer für den Kernel erzeugt dafür aber noch keinen Code, und der Kernel selbst kommt ohne wiederhole aus.
  • Ein eigenes „sonst wenn“ fehlt. Ein zweites wenn steht im sonst-Teil und braucht sein eigenes ende:
wenn zähler == 0
    zähler = 1
sonst
    wenn zähler == 1
        zähler = 2
    ende
ende

Weiter

Version 9.0.0

Die Webseite wiegt die Hälfte, das Menü auf dem Telefon ist eine Liste geworden, das Glas ist überall dasselbe — und ein Kasten auf der Startseite sagt, warum hier eine Weile nichts passiert.