Assembly Nights

Mijn trouwe eeePC 701 is een 32-bit Celeron "netbook" minilaptop uit 2007 die momenteel op Alpine Linux draait. Op dit apparaat werk ik aan mijn vroege versie van een NASM-port van "JonesForth". Deze kleine computer heeft meer versies van Linux en BSD gedraaid dan ik kan tellen. Bovendien is hij heerlijk warm op een koude nacht.

Mijn interesse in de programmeertaal Zig heeft geleid tot een diepere interesse in "systems-level" programmeren, wat uiteindelijk weer leidt naar computerarchitectuur, instructiesets en assembly-talen. Het voltooide project heeft overigens ook een eigen pagina: nasmjf.

De leeromgeving

Om redenen die ik niet kan verklaren, voelt het simpelweg goed om mijn kleine computer met zijn kleine toetsenbord te gebruiken om laat op de avond kleine instructies te typen. Ik vermoed dat het feit dat ik me in een volledig andere omgeving bevind dan bij mijn normale desktop-ontwikkelmachines, me in een ontvankelijke leerstem brengt.

Daarnaast is dit, hoewel ik Lynx heb geïnstalleerd, geen geweldige machine voor modern websurfen (behalve voor ratfactor.com natuurlijk). Het is dus een apparaat zonder afleidingen.

Omdat deze kleine computer voor niets anders wordt gebruikt, heb ik hem langzaam aangepast voor deze ene taak: wanneer ik inlog, voert mijn .bash_profile-script direct een cd uit naar mijn assembly-projectmap. Ik heb een reeks cryptische scripts en aliassen van één of twee letters die mijn project en de bijbehorende documentatie openen in Vim, of de GDB-debugger starten en een GDB-script uitvoeren met een breakpoint bij het laatste punt waar ik aan werkte.

Deze kleine aanpassingen maken het veel gemakkelijker om aan de slag te gaan wanneer ik moe ben en geen grote inspanning wil leveren. Inmiddels is het pakken van de eeePC, inloggen en het openen van het assembly-project een automatisme geworden, net als tandenpoetsen.

Het porteren van JonesForth

Direct na het voltooien van de lessen op asmtutor.com (zie NASM onder Bronnen), begon ik aan een van de "bucket list"-projecten die ik lang geleden had geparkeerd: het lezen en begrijpen van JONESFORTH van Richard WM Jones. Er zijn een paar mirrors van de JonesForth-broncode op Github; ik heb deze kopie gebruikt: https://github.com/nornagon/jonesforth.

Ik wilde echter niet alleen lezen, dus heb ik besloten het te porteren naar NASM. De voortgang is ongelooflijk traag geweest omdat ik nieuw ben in assembly in het algemeen en NASM in het bijzonder. JonesForth is geschreven in GAS (de GNU Assembler) met een volledig andere syntaxis. Zelfs de machine-instructie mnemonics verschillen, omdat GAS vaak de grootte van de data die wordt gemanipuleerd opneemt als onderdeel van de mnemonic. (Voor een uitgebreidere tirade over deze syntaxis kan men kijken naar "Why no one should use the AT&T syntax ever, for any reason, under any circumstances").

De grootste initiële uitdaging was het porteren van enkele essentiële macro's van GAS naar NASM. Het kostte weken om elke macro te begrijpen en om te zetten. Toch is het geweldig en bevredigend om aan iets niet-triviaals te werken, zelfs als het in het begin ver boven mijn macht was. Ik heb vaker willen opgeven, maar ik blijf doorzetten en de barrières wijken langzaam. Elke keer dat ik begrijp wat een nieuwe instructie doet of een bug oplos, voelt dat als een kleine overwinning.

De Repository

Dit is de repository met mijn voortgang: https://github.com/ratfactor/nasmjf. Kijk in het bijzonder naar de logbestanden (log01.txt, log02.txt, etc.). Deze documenteren mijn beproevingen. Ik wenste dat ik dit vanaf het begin had gedaan, maar ik ben blij dat ik het nu doe.

Vertragen, genieten van het proces en tools leren

Deze sectie is een update:

Onlangs heb ik "per ongeluk" een deadline gesteld aan de JonesForth-port. Ik wilde een aantal kleine projecten die ik dit jaar heb opgebouwd afronden, zodat ik me volgend jaar meer eenduidig op een paar grotere projecten kan concentreren. Maar zodra ik die deadline had, gebeurde het volgende: ik begon me te haasten door blokken JonesForth-assembly en zette ze zo snel mogelijk om naar NASM. Dom, toch?

Ik wist dat ik mezelf moest dwingen te vertragen, maar dat is makkelijker gezegd dan gedaan. Een gevoel van urgentie is snel verworven, maar niet zo makkelijk weer kwijt te raken.

Mijn "douche-epifanie" van gisteravond (dagen nadat ik dit oorspronkelijke artikel schreef) was hoe ik die vertraging aan moest pakken: ik stop met de vertaling waar ik nu ben, herstel alle syntaxis-fouten zodat het geheel assembleert, en loop vervolgens elke instructie die ik tot nu toe heb geschreven na om te controleren of alles werkt zoals verwacht. Om dit leuker te maken en daadwerkelijk resultaat te hebben, ga ik de hele sessie loggen. Aangezien ik geen X op deze computer heb, is GNU Screen, de terminal-multiplexer, de logische keuze voor logging.

Mijn eerste gedachte was: "geweldig, nu moet ik nog een tool leren en raak ik volledig afgeleid!" Mijn tweede gedachte was echter: "wacht, dat is juist geweldig." Nu kan ik eindelijk een andere grote, alomtegenwoordige GNU-applicatie fatsoenlijk leren kennen en een tool hebben waar ik me zeker bij voel. Bovendien denk ik dat Screen nuttig zal zijn voor diverse gemakkelijke verbeteringen. Momenteel gebruik ik de virtuele terminals van Linux (Alt-F1, Alt-F2, etc.) om zowel een Vim-sessie als een GDB-sessie open te hebben voor referentie. Deze moet ik handmatig beheren. Met Screen kan ik waarschijnlijk het openen van beide met één commando automatiseren en ertegen wisselen met Ctrl-a, Ctrl-a.

Ik ben momenteel de volledige GNU Screen User’s Manual aan het lezen en alles uit te proberen. Daarna ga ik een uitgebreide GDB-sessie loggen en daar een transcript van maken, wat als een nieuw artefact in de repository kan komen. Ik stel me een reeks korte sessietranscripts voor waarin ik elke nieuwe functionaliteit exploreer.

(Update: Ik doe dit! Bekijk de logbestanden in de repository).

Het punt is dat ik mijn weg even kwijt was door de voltooide Forth-port als het "doel" van deze oefening te zien. Dat is het niet. Het leerproces en de vaardigheden die ik verwerf, zijn het doel. Bovendien zullen de Assembly Nights, zodra de port klaar is, veranderen in Forth Nights. Ik heb Leo Brodie's Starting Forth en Thinking Forth op mijn nachtkastje liggen. Deze reis zal dus duren hoe lang het duurt, en het zal glorieus zijn.

Rust vinden in het langzame pad

Ik hou van projecten. Waarschijnlijk iets te veel. De meeste van mijn projecten zijn gedoemd te mislukken. Ze lijken in het begin allemaal een succes. Vaak realiseer ik me pas dat een project gaat mislukken nadat ik er veel tijd in heb geïnvesteerd, omdat de fout in het grote plaatje zat terwijl ik me concentreerde op de leuke details. De meeste van mijn projecten branden fel en doven dan uit.

Dat is oké, maar als het te vaak gebeurt, kan het depressief worden. Wat ik echter ben gaan beseffen, is dat er projecten zijn die gegarandeerd succesvol zijn, simpelweg door eraan te werken.

Op dit moment heb ik twee van zulke projecten:

  1. Dit project.
  2. Mijn htmx-voorbeeldenpagina — codevoorbeelden voor elk htmx-concept (en grappige dierentekeningen!).

Beide hebben al een duidelijke richting; elke dag dat ik eraan werk, maak ik gegarandeerd vooruitgang. Ik ben dit niet gewend en ik geniet ervan. De beloningen zijn traaaaag, maar de enige manier om te falen is door ermee te stoppen. Comfortabel!

Bronnen

NASM

De NASM-assembler wordt geleverd met documentatie in de vorm van één tekstbestand. Ik heb dit bestand openstaan naast mijn assembly-bronbestand, zodat het altijd slechts één Vim-buffer verwijderd is. De inhoud is hetzelfde als in de HTML-versie.

Voor wie wil beginnen: mijn pad (dat ik sterk aanbeveel) was om eerst de basis van assembly te leren met de heldere "Intel-stijl" syntaxis van NASM. Hiervoor raad ik zeer aan: https://asmtutor.com/ - NASM Assembly Language Tutorial door Daniel Givney.

Je hebt een Linux-computer nodig (of iets virtueels zoals WSL op Windows), aangezien de tutorials vertrouwen op Linux-systeemoproepen. Ik heb alle oefeningen op de eeePC gedaan, onder de dekens, met asmtutor.com open op mijn telefoon.

Wat ik geweldig vind aan asmtutor.com (naast dat het precies is wat ik zocht en volledig gratis is), is dat je een enorme hoeveelheid functionaliteit bestrijkt — van "Hello World" tot een multi-threaded webserver — in hapklare lessen. Ook bouw je een bibliotheek van kleine nuttige functies op die je als startpunt voor andere projecten kunt gebruiken.

Ik heb veel inzicht gekregen door gebruik. Elke les bestaat uit een paar uitleggende paragrafen en een assembly-programma. Ik pas de voorbeelden altijd aan om zeker te weten dat ik ze begrijp, waardoor mijn functies al vroeg afweken van de originelen. Het herhaaldelijk gebruiken van push, pop, call en ret in deze oefeningen deed meer voor het concretiseren van deze fundamentele concepten dan jaren aan theorie en programmeren in high-level talen.

(Eigenlijk heb ik in mijn jeugd een DOS-gebaseerd x86 assembly-boek gelezen en genoten van het schrijven van DOS-programma's met niets anders dan debug, maar dat was voordat ik echt veel had geprogrammeerd. De ervaring sloeg deze keer dus anders aan.)

GDB

GDB is een enorme en intimiderende software (praktisch een besturingssysteem), dus ik heb het fysieke boek Debugging with GDB: The GNU Source-Level Debugger gekocht, direct van GNU Press/FSF. Ik las het boek in het weekend op de bank en maakte bladwijzers voor zaken die ik die avond op de eeePC wilde proberen.

Natuurlijk is de GDB-handleiding ook gratis online te lezen: https://sourceware.org/gdb/current/onlinedocs/gdb/.

x86 Assembly Language

Er is een erg mooi overzicht met een lijst van veelvoorkomende instructies geschreven door Adam Ferrari. Ik ontdekte onlangs dat dit bestaat in "Intel-stijl" bij de University of Virginia: https://www.cs.virginia.edu/~evans/cs216/guides/x86.html ("Intel") en in GAS/AT&T-syntaxis bij Yale: https://www.cs.yale.edu/flint/cs421/papers/x86-asm/asm.html ("AT&T")

Ik heb ook een fysiek exemplaar van het zeer aanbevolen boek Programming From the Ground Up: An Introduction to Programming Using Linux Assembly Language door Jonathan Bartlett. Dit boek gebruikt GAS. Logischerwijs had ik daar mee moeten beginnen, daarna de asmtutor.com-tutorials voor NASM moeten doen, en dan pas mijn JonesForth-port moeten starten...

...Maar ik geloof eigenlijk dat het boek nu veel beter zal blijven hangen, omdat ik sommige dingen al op de harde manier heb geleerd. Dit past perfect bij mijn eigen theorie over leren: The Phenomena of the Game Manual.