Geschrieben wie Python, übersetzt für Windows und das ESP32-Board, Zeile für Zeile debuggt in Asmonite.
aBelle hat wenige Wörter, drei Typen und keine verborgenen Regeln. Ihr Compiler ist selbst in aBelle geschrieben. Er schreibt den Maschinencode und die Programmdatei selbst, ohne Assembler und ohne Linker. In Asmonite drückst du F9: Das Programm wird übersetzt und läuft im Debugger, mit Breakpoints, Schritten durch die Zeilen und den Werten der Variablen.
aBelle liegt ab Asmonite 0.12.0 im ZIP: die drei Compiler abelle.exe, abelle64.exe und abelle_esp32.exe neben Asmonite.exe, die Beispiele in examples\abelle und die F1-Hilfe. Es gilt die Lizenz von Asmonite: kostenlos, und was du damit schreibst, gehört dir.
Links ein Programm für Windows: Es holt sich WriteFile aus kernel32.dll und schreibt auf die Konsole. Rechts eines für das ESP32-Board: Die Register des Chips sind Felder an ihrer Adresse, und die LED blinkt.
extern "kernel32.dll": def GetStdHandle(n: i32) u32 def WriteFile(h: u32, buf: pchar, n: u32, written: pchar, ov: u32) i32 written: char[4] def strlen(s: pchar) i32: n = 0 while s[n] != 0: n += 1 return n def print(s: pchar): WriteFile(GetStdHandle(-11), s, u32(strlen(s)), written, 0) def main() i32: print("Hello, world!\n") return 0
target "esp32" gpio: u32[0x140] at 0x3FF44000 # the GPIO registers iomux: u32[64] at 0x3FF49000 # the function of each pin LED = 2 def wait(): for i in 0..500000: pass # about half a second def main(): iomux[0x40 / 4] = 0x2800 # GPIO 2 is a GPIO gpio[(0x530 + 4 * LED) / 4] = 0x100 gpio[0x24 / 4] = 1 << LED # an output while True: gpio[0x08 / 4] = 1 << LED # on wait() gpio[0x0C / 4] = 1 << LED # off wait()
Die Dateien heißen .abel. Ein Block folgt auf eine Zeile mit : und ist vier Leerzeichen weiter eingerückt, wie in Python. Ein Programm für ein Board sagt das in seiner ersten Zeile mit target; ohne sie ist es eines für Windows.
aBelle ist bewusst klein: genau so viel, wie ein Compiler braucht, um sich selbst zu übersetzen, und dazu die Register eines Boards. Alles im Einzelnen steht in der Sprachbeschreibung (vorläufige Fassung).
| Was | Wie |
|---|---|
| Typen | i32 (der Standard), u32 für Adressen und Bitmuster, pchar die Adresse eines Bytes. Umwandeln immer ausdrücklich: u32(x) |
| Variablen | global mit Typ: count: i32 = 0; lokal bei der ersten Zuweisung: n = 0 |
| Felder | fest: names: i32[100], src: char[2000]; wachsend: toks: i32[] mit append, len, resize; an einer Adresse: gpio: u32[0x140] at 0x3FF44000 |
| Funktionen | def add(a, b) i32:; Rekursion; eine Funktion darf vor ihrer Stelle benutzt werden |
| Abläufe | if / elif / else, while, for i in 0..n:, break, continue, return |
| Rechnen | die Operatoren von Python für ganze Zahlen, dazu x += 1 und die anderen; / schneidet zur 0 hin ab wie die Hardware |
| Windows | Funktionen einer DLL mit extern "kernel32.dll":, auch cdecl und ... für printf |
| Boards | target "esp32" in der ersten Zeile; Register als Feld at ihrer Adresse, eine Funktion des ROM mit def ets_delay_us(us: u32) at 0x40008534 |
| Mehrere Dateien | include "inc/uart.abel" fügt den Text einer Datei ein, jede Datei einmal |
Dieselbe Sprache, drei Compiler, jeder aus derselben Quelle bis auf den Teil, der den Code und die Datei schreibt.
| Windows x86 | Windows x64 | ESP32 | |
|---|---|---|---|
| Compiler | abelle.exe | abelle64.exe | abelle_esp32.exe |
| Wahl | der Standard | Project > aBelle for x64 | target "esp32" |
| Ausgabe | ein Konsolenprogramm (PE) | ein Konsolenprogramm (PE32+) | Code für das IRAM, Daten für das DRAM |
| F9 | übersetzt und startet im Debugger | lädt über das USB-Kabel ins RAM; Shift+F9 schreibt es zuerst in den Flash | |
Auf dem ESP32 kann ein aBelle-Programm auch als Datei auf dem Board liegen: Debug > ESP32 Board Files lädt es in die Konsole von examples/esp32/console.asm, die es startet, auf Wunsch nach jedem Reset.
Die Beispiele für den ESP32 binden Dateien aus examples\abelle\esp32\inc ein. Sie sind selbst in aBelle geschrieben: Du kannst sie lesen, ändern und im Debugger verfolgen.
| Datei | Was sie bringt |
|---|---|
uart.abel | Text, Zahlen und Hexzahlen über UART0, den COM-Port des Boards |
wifi.abel | das WLAN: den Dienst vom Board laden, Netze suchen, sich verbinden, Frames senden und empfangen, Fehler als Satz |
net.abel | ARP, IPv4, ICMP (Ping), UDP, DHCP, DNS und mDNS |
tcp.abel | TCP, eine Verbindung zur Zeit, als Client oder Server |
network.abel | der Name und das Passwort deines WLAN |
Das WLAN selbst läuft auf dem zweiten Kern des ESP32, das aBelle-Programm auf dem ersten. Hält der Debugger das Programm an einem Breakpoint an, bleibt die Verbindung stehen, und was ankommt, wartet in einem Puffer. So gehst du Zeile für Zeile durch einen DHCP-Austausch oder eine TCP-Verbindung. Einmal pro Board braucht es dafür Install WiFi; mehr auf der ESP32-Seite.
Der Compiler schreibt neben das Programm eine Map-Datei: welcher Code zu welcher Zeile gehört und wo die Variablen liegen. Asmonite debuggt damit direkt in der .abel-Datei.
pchar mit seinem Text, Felder als Liste, wachsende Felder mit ihrer LängeaBelle ist so entstanden, wie Sprachen früher entstanden sind: in Stufen, bis die Sprache sich selbst trägt.
Der Compiler arbeitet in einem Durchgang: lesen, zerlegen und sofort Code schreiben, ohne Syntaxbaum. Über 350 Tests und ein Fuzzer mit zufälligen Programmen prüfen, dass alle Compiler dasselbe tun.
| Windows | ESP32 |
|---|---|
hello.abel – Hello, world! | blink.abel – die LED blinkt |
factorials.abel – Rekursion | hello_uart.abel – Text über die serielle Schnittstelle |
table.abel – das Einmaleins | timer.abel – Mikrosekunden mit dem Timer |
fizzbuzz.abel – if / elif / else | temperature.abel – der Sensor im Chip |
primes.abel – das Sieb des Eratosthenes | chipinfo.abel, dice.abel, sieve.abel |
strings.abel, printf.abel – Text | reaction.abel – ein Reaktionsspiel, clock.abel – der Takt |
WLAN: scan, dhcp, dns, ping, ntp, arpscan, wol, udpecho, httpget, webserver, telnetd |
Die Beispiele für Windows liegen in examples\abelle, die für den ESP32 in examples\abelle\esp32. Alle ESP32-Beispiele mit Beschreibung →
include fügt nur Text ein), Zahlen mit 64 Bit.f(i)[0]) und der Ausdruck x and a or b als Auswahl gehen nicht; eine Hilfsvariable tut es.inc stellen ihren Namen darum ein Kürzel voran (wl_, u_, md_).