Uitvoerbare Emoji

Een hele reeks emoji. Wat zouden ze kunnen betekenen?

Dit specifieke bericht is wat onverwacht. Ik was aan het experimenteren met een webapplicatie die ik had gemaakt — een online disassembler voor de x86 — toen ik merkte dat emoji in de url werden gecodeerd.

Ik plakte een geit-emoji (🐐) en merkte de codering %F0%9F%90%90 op. Als je enigszins bekend bent met de x86 assembly-taal, is hexadecimaal 90h waarschijnlijk bekend bij je. Het is de opcode voor een 'null operation' of NOP.

Ik lachte kort om de gedachte dat geiten de NOP's van emoji waren, maar daarna werd ik nieuwsgierig. F0h op de 8088 is het LOCK-prefix. Dit prefix wordt over het algemeen gebruikt om exclusieve bus toegang te coördineren met een coprocessor zoals de 8087, maar doet verder niets voor de meeste instructies op de 8088 en wordt genegeerd (dit zou veranderen bij latere Intel CPU's). Dat laat ons over met 9Fh.

9Fh is LAHF.

De volledige geit-emoji is dus geldige 8088 machinecode, een sequentie die leest als: lock lahf nop nop

Het blijkt dat de overgrote meerderheid van de emoji-grafemen, zoals ze worden genoemd, beginnen met de sequentie F09F. Er ging een lampje in mijn hoofd branden: zou je daadwerkelijk een 8088-programma kunnen schrijven met niets anders dan weergavebare emoji?

Het idee is niet zonder precedent. Het staat al lang vast dat executables gegenereerd kunnen worden met alleen printbare ASCII-tekens — het bekendste voorbeeld is waarschijnlijk het EICAR-testbestand, een ASCII-string die ook een geldig DOS-executable is die "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!" print en afsluit.

Andere kleine ASCII-programma's werden in tijdschriften gedrukt of op andere manieren verspreid, zoals de kleine terminal-utility TCOM, waarvan de volledige broncode hieronder staat:

XPHPD[0GG0G,0G51G31GB'(G+(G:u'0g?(G>(GE1G@arwIVF*=US@>1|,5wXNg-7muTu(4 1m0ss1k260s@3G1g360@3G0i7t2g3A1g350@3G2E1=0C1g350@3T2M0^\1g3>0@3T=1s2g0T 1g3;0@3ToN2g391g0t@3G0^F1k0s2?0@3T4

Dit is een interessante "noodoplossing" voor terminals: als iemand geen andere manier had om een executable op een computersysteem te laden, kon deze simpelweg via het toetsenbord worden ingevoerd. Het verrast me dat het idee om direct emoji uit te voeren blijkbaar nooit eerder is verkend.

Hello (World)!

Natuurlijk is het eerste wat je doet एक poging tot "Hello World!" in emoji. Om ruimtebesparende redenen en gedeeltelijk vanwege de moeite die het kost om enige vorm van rekenkunde in emoji uit te voeren, printen we alleen de string HELLO.

Hier is het volledige programma: 🐸☺️🐰🐎♐<0xF0><0x9F><0x97><0x83>️<0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>🐮💗<0xF0><0x9F><0xA6><0xAE><0xF0><0x9F><0xAA><0x8F>♐🐰🐹<0xF0><0x9F><0x97><0x83>️<0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>💗<0xF0><0x9F><0xAA><0x97><0xF0><0x9F><0xA7><0xAF>😗<0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xAB><0xAA>😗<0xF0><0x9F><0xA7><0xAE>😗🐮😪😔⭐

Wanneer dit in een teksteditor wordt geplakt en opgeslagen als UTF-8 (zonder BOM) met een .COM-extensie, zou het resultaat 141 bytes moeten zijn met een MD5-som van 0a5c91475ca2de33e36aacc2f0b7b840.

Sommige emoji kunnen hier als "tofu" (vierkantjes) worden weergegeven, afhankelijk van je browser en het jaar waarin je dit artikel leest.

  • <0xF0><0x9F><0xAA><0x8F> is de schep-emoji, geïntroduceerd in Unicode 16.0 in 2024. Deze glyphs hebben tijd nodig om door te sijpelen naar font-updates.
  • <0xF0><0x9F><0xAA><0x97> is de accordeon-emoji, toegevoegd aan Unicode 13.0 in 2020, maar omens nog niet zichtbaar in Chrome op Windows 10.
  • <0xF0><0x9F><0xAB><0xAA> is de "Distorted Face" emoji en is gloednieuw in Unicode 17.0, goedgekeurd in 2025.

In theorie zou het mogelijk moeten zijn om het relevante tofu-karakter te kopiëren en de representatieve bytes te behouden, maar sommige besturingssystemen en programma's lijken moeite te hebben met dit concept van byte-behoud.

Dit programma vertrouwt op een paar ongedocumenteerde 8088-aliassen en vereist daarom een vrij nauwkeurige 8088-core om succesvol te worden uitgevoerd. Laten we kijken wat het doet in DOSBox-X met cpu cputype=8086.

Het programma begint met 🐸☺️. Deze sequentie voert enkele belangrijke instellingen uit en verklaart hoe we een pointer naar het videogeheugen krijgen. Deze emoji vertegenwoordigen de byte-sequentie F09F90B8E298BAEFB88F:

00000000  F0 9F     lahf
00000002  90        nop
00000003  B8 E2 98  mov ax,98E2h
00000006  BA EF B8  mov dx,B8EFh
00000009  8F        db 0x8F

B8EFh bevindt zich nog steeds binnen het basis B800 tekstmodus video-segment, ongeveer 3.824 bytes in het scherm, wat verklaart waarom onze tekst in de rechterbenedenhoek van het scherm verschijnt. We doen alsof deze tekstpositionering volledig opzettelijk was.

De 💗 emoji (F09F9297) verplaatst ons video-segment naar DI:

0000012C  F0 9F  lahf
0000012E  92     xchg dx,ax
0000012F  97     xchg di,ax

De letters worden gesynthetiseerd beginnend met de H. <0xF0><0x9F><0x97><0x83>️ (F09F9783EFB88F) is hier cruciaal:

00000146  83 EF B8  sub di,FFB8h

Aftrekken van FFB8h is equivalent aan optellen van 48h. Wat is de ASCII-hexcode voor 'H'? 48h. Vernuftig.

De rest van de letters wordt onhandig één voor één gesynthetiseerd. De L kan natuurlijk herhaald worden. Je zult merken dat een van de L's groen is. Dit wordt veroorzaakt doordat een van de LAHF-instructies AH overschrijft. Toevalligerwijs vertegenwoordigen de inhoud van het vlagregister een zichtbaar karakter-attribuutbyte — in dit geval groen. Het attribuut zou gereset kunnen worden ten koste van een paar extra bytes, maar ik vind de mismatch leuk als kleine hint naar de "vervloekte" zaken die zich achter de schermen afspelen.

Referentietabel voor 'Emojissembly'

Als je dapper genoeg bent om zelf emoji-code te schrijven, kunnen de volgende referenties helpen.

Standalone Emoji

Er zijn een paar standalone emoji die nuttige instructies of instructieparen vertegenwoordigen.

EmojiUTF-8 bytes8088 interpretatieNuttig effect en typisch gebruik
🐐F0 9F 90 90LAHF; NOP; NOPPadding van vier bytes. Ook nuttig in een loop-body wanneer een exacte branch displacement nodig is.
🐮F0 9F 90 AELAHF; NOP; SCASBDI += 1. Een kleine, schone pointer-increment.
😯F0 9F 98 AFLAHF; CBW; SCASWDI += 2. Compacter dan twee 🐮; AX wordt de tekensverlenging van AL.
<0xF0><0x9F><0xA7><0xAE>F0 9F A7 AELAHF; CMPSW; SCASBSI += 2, DI += 3. Nuttig wanneer SI ook vooruit moet gaan. Leest DS:SI en ES:DI en verandert vlaggen.
<0xF0><0x9F><0xA7><0xAF>F0 9F A7 AFLAHF; CMPSW; SCASWSI += 2, DI += 4. Een compacte vier-byte advance. Ook nuttig in het geval van 🔥.
🤐F0 9F A4 90LAHF; MOVSB; NOPKopieert één byte van DS:SI naar ES:DI, en incrementeert beide pointers.
😬F0 9F 98 ACLAHF; CBW; LODSBLaadt één byte van DS:SI in AL, en incrementeert SI.
🐪F0 9F 90 AALAHF; NOP; STOSBSchrijft AL naar ES:DI, en incrementeert DI.
😖F0 9F 98 96LAHF; CBW; XCHG AX,SIVerplaatst de tekensverlengde AL naar SI terwijl de oude SI in AX wordt bewaard. Nuttig na het verkrijgen van een bekende nul.
😗F0 9F 98 97LAHF; CBW; XCHG AX,DITransfereert een tekensverlengde byte tussen AX en DI. Nuttig om AL=F0h om te zetten in DI=FFF0h.
📗F0 9F 93 97LAHF; XCHG AX,BX; XCHG AX,DIRoteert waarden via AX, BX en DI. De byte-writer gebruikt dit om een bewaarde outputpointer te herstellen en de gesynthetiseerde byte in AL terug te winnen.
👁️F0 9F 91 81 EF B8 8FLAHF; XCHG AX,CX; SUB DI,8FB8hVoegt 7048h toe aan DI. Uitstekend voor grote modulaire pointer-bewegingen; overschrijft AX en CX.

Emoji met open uiteinden

Het wordt bijzonder interessant wanneer we emoji aan elkaar rijgen vanaf een emoji die een "open uiteinde" of incomplete instructiebyte achterlaat. De volgende emoji laten een bungelende byte achter die zeer nuttig kan zijn, afhankelijk van de emoji die volgt:

EmojiUTF-8 bytesOpen uiteindeVeelvuldig gebruik
🐸F0 9F 90 B8MOV AX,imm16 heeft twee bytes nodigAbsorbeert het begin van ☺️ om MOV AX,98E2h te creëren.
☺️E2 98 BA EF B8 8FEerste twee bytes kunnen een immediate zijn; laatste 8Fh heeft een ModR/M nodigNa 🐸 levert dit MOV AX,98E2h; MOV DX,B8EFh en opent een POP.
🐰F0 9F 90 B0MOV AL,imm8 heeft één byte nodigConsumeert een volgende F0h, of consumeert de E2h aan het begin van ☃️.
🐹F0 9F 90 B9MOV CX,imm16 heeft twee bytes nodigConsumeert een volgende F0 9F header om CX=9FF0h te laden.
🐎F0 9F 90 8EMOV Sreg,r/m16 heeft een ModR/M byte nodigGevolgd door de E2h van ♐ geeft dit de 8088-only alias MOV ES,DX.
😿F0 9F 98 BFMOV DI,imm16 heeft twee bytes nodigConsumeert de F0 9F header van de volgende emoji en reset DI=9FF0h.
🍽️F0 9F 8D BD EF B8 8FPOP r/m16 heeft een ModR/M byte nodigVoegt eerst B8EFh toe aan DI; een volgende F0h voltooit de ongedocumenteerde POP AX, zodat SP += 2.
☃️E2 98 83 EF B8 8FBegint en eindigt met bytes bedoeld voor burenNadat 🐰 de E2h consumeert, voert het midden SUB DI,-72 uit; de afsluitende 8Fh heeft een ModR/M nodig.
🗓️F0 9F 97 93 EF B8 8FFinale B8 8F consumeert de volgende F0hBewaart de outputpointer in BX terwijl de byte-accumulator naar DI wordt verplaatst. Voert ook OUT DX,AX uit.
E2 AD 90Eerste twee bytes zijn LOOP -83Een drie-byte loop-tail wanneer de loop-body precies op de juiste afstand is geplaatst.

Nuttige Gadgets

Dit zijn complete, nuttige sequenties van meerdere emoji.

BunnySad: 🐰😔 — Stackherstel

Deze acht-byte sequentie vervangt bewust de huidige stack pointer door FFF0h:

0000: F0 9F    lahf
0002: 90       nop
0003: B0 F0    mov al,F0h
0005: 9F       lahf
0006: 98       cbw
0007: 94       xchg sp,ax

De finale B0h van het konijn consumeert de leidende F0h van het verdrietige gezicht, waardoor AL=F0h wordt geladen. De tweede LAHF wordt gevolgd door CBW, wat dit omzet in AX=FFF0h; XCHG installeert dit vervolgens als de stack pointer. Dit is hoe men herstelt na opzettelijke POP's en asynchrone interrupt pushes nabij de top van het segment houdt. Het gooit de huidige stack weg, dus het is alleen veilig wanneer er geen return-adres of bewaarde waarde actief is. De oude SP blijft in AX achter.

BunnySnowParty: 🐰☃️🐰😔 — Veilige optelling: DI += 48h

Deze 18-byte sequentie verhoogt DI met 48h (72 decimaal), absorbeert de bungelende POP van de sneeuwpop en herstelt de stack:

0000: F0 9F       lahf
0002: 90          nop
0003: B0 E2       mov al,E2h
0005: 98          cbw
0006: 83 EF B8    sub di,FFB8h
0009: 8F F0       pop ax
000B: 9F          lahf
000C: 90          nop
000D: B0 F0       mov al,F0h
000F: 9F          lahf
0010: 98          cbw
0011: 94          xchg sp,ax

Het eerste konijn consumeert de E2h van de sneeuwpop; B8h is een signed -72 immediate, dus SUB DI,-72 telt 72 op. De finale 8Fh van de sneeuwpop consumeert de F0h van het volgende konijn als de ongedocumenteerde POP AX codering 8F F0. Het laatste konijn/verdrietig-gezicht paar herstelt SP=FFF0h.

PlateGoat: 🍽️🐐 — SP incrementeren en DI verplaatsen

Het bord heeft een volgende byte nodig om de finale 8Fh te voltooien. Een padding-geit is een handige, ongevaarlijke staart.

0000: F0 9F          lahf
0002: 8D BD EF B8    lea di,[di-4711h]
0006: 8F F0          pop ax
0008: 9F             lahf
0009: 90             nop
000A: 90             nop

B8EFh is de 16-bit representatie van -4711h, dus de LEA voert DI += B8EFh uit. De 8Fh van het bord consumeert de leidende F0h van de geit als ongedocumenteerde POP AX; de resterende 9F 90 90 is LAHF; NOP; NOP. Borden verhogen SP met twee alsook DI over een aanzienlijke afstand te verplaatsen.

CatGoat: 😿🐐 — Absolute DI reset

De huilende kat opent MOV DI,imm16. Een padding-geit levert de immediate value.

0000: F0 9F       lahf
0002: 98          cbw
0003: BF F0 9F    mov di,9FF0h
0006: 90          nop
0007: 90          nop

Deze acht-byte gadget reset DI naar 9FF0h zonder afhankelijk te zijn van de vorige waarde.

CamelWrite: 🗓️ + rekenkunde + 📗🐪 — Een byte genereren en schrijven

De algemene vorm is 15 vaste bytes plus de gekozen rekenkundige sequentie. Hier is het eenvoudigste concrete voorbeeld, 🗓️🐮📗🐪, waarbij een koe wordt gebruikt om één op te tellen:

0000: F0 9F       lahf
0002: 97          xchg di,ax
0003: 93          xchg bx,ax
0004: EF          out dx,ax      ; spurious OUT naar B8EFh
0005: B8 8F F0    mov ax,F08Fh
0008: 9F          lahf
0009: 90          nop
000A: AE          scasb
000B: F0 9F       lahf
000D: 93          xchg bx,ax
000E: 97          xchg di,ax
000F: F0 9F       lahf
0011: 90          nop
0012: AA          stosb

Bij binnenkomst is DI de echte outputpointer en bevat AX de rekenkundige seed. 🗓️ verplaatst de seed naar DI en bewaart de outputpointer in BX. De middelste emoji-sequentie voert rekenkunde uit op deze tijdelijke DI; de koe hierboven telt één op. 📗 herstelt de outputpointer en transfereert de berekende low byte naar AL, en 🐪 schrijft deze. De kalender voert ook OUT DX,AX uit. De gebruikelijke startup stelt DX=B8EFh in, een over het algemeen niet-toegewezen poort. Gebruik dit met voorzichtigheid op echte hardware!

FrogStrap: 🐸☺️😖🐰😗😯😯😯😯😯😯😯 — Algemene register bootstrap

Deze 50-byte sequentie verkrijgt een bekende nul uit de normale COM-entry stack en stelt een specifieke registerstatus in:

0000: F0 9F       lahf
0002: 90          nop
0003: B8 E2 98    mov ax,98E2h
0006: BA EF B8    mov dx,B8EFh
0009: 8F F0       pop ax
000B: 9F          lahf
000C: 98          cbw
000D: 96          xchg si,ax
000E: F0 9F       lahf
0010: 90          nop
0011: B0 F0       mov al,F0h
0013: 9F          lahf
0014: 98          cbw
0015: 97          xchg di,ax
0016: F0 9F       lahf
0018: 98          cbw
0019: AF          scasw
001A: F0 9F       lahf
001C: 98          cbw
001D: AF          scasw
001E: F0 9F       lahf
0020: 98          cbw
0021: AF          scasw
0022: F0 9F       lahf
0024: 98          cbw
0025: AF          scasw
0026: F0 9F       lahf
0028: 98          cbw
0029: AF          scasw
002A: F0 9F       lahf
002C: 98          cbw
002D: AF          scasw
002E: F0 9F       lahf
0030: 98          cbw
0031: AF          scasw

🐸☺️ laadt DX=B8EFh en laat een bungelende 8Fh achter. De eerste byte van 😖 voltooit POP AX, waardoor de bekende nul op SS:FFFEh wordt verkregen en SP naar 0000h wrapt; de rest van 😖 verplaatst die nul naar SI. 🐰 consumeert de leidende F0h van 😗 om AL=F0h te maken, waarna CBW; XCHG DI,AX zorgt voor DI=FFF0h. Zeven SCASW's verplaatsen dit naar FFFEh. De uiteindelijke status is DX=B8EFh, SI=0000h, DI=FFFEh, en SP=0000h. De waarde van B8EFh in DX bevindt zich in het onderste gedeelte van het CGA-videogeheugen als dit als segment wordt gebruikt. Een extra 😯 kan DI laten overrollen naar 0000h. De waarde FFFEh die in DI achterblijft, heeft mogelijke toepassingen als een -2 constante.

🐸☺️🐰🐎♐ — Het CGA-segment laden

Deze 21-byte sequentie maakt gebruik van de ongedocumenteerde segment-register alias van de originele 8088 om ES=B8EFh in te stellen:

0000: F0 9F       lahf
0002: 90          nop
0003: B8 E2 98    mov ax,98E2h
0006: BA EF B8    mov dx,B8EFh
0009: 8F F0       pop ax
000B: 9F          lahf
000C: 90          nop
000D: B0 F0       mov al,F0h
000F: 9F          lahf
0010: 90          nop
0011: 8E E2       mov es,dx
0013: 99          cwd
0014: 90          nop

Een basisloader

Om eerlijk te zijn is direct schrijven in 'emojissembly' een ellendig en pijnlijk proces, door het gebrek aan redelijke immediate values, rekenkundige bewerkingen of zinvolle jump-offsets. Daarom is het verstandig om een loader te bouwen die simpelweg 8088-code in het geheugen kan opbouwen en er vervolgens naartoe springt.

De truc is hoe je willekeurige byte-data codeert in emoji. Met minder dan 4000 grafemen zijn emoji nauwelijks een 16-bit LUT. In feite komen niet alle 256 8-bit waarden voor in de 4-byte grafemenset op zowel de derde als de vierde bytepositie; echter, door puur geluk kunnen we een 8-bit look-up table construeren vanuit de 2-byte staart van een set van 256 unieke emoji.

Dit is het basisidee:

bits 16
org 0
push di
pop  si                         ; SI = gecodeerde emoji data
mov  di,0100h
push di                         ; RET target na reconstructie
mov  cx,RAW_SIZE
.decode:
lodsw                           ; negeer het vaste F0 9F prefix
lodsw                           ; AL=derde UTF-8 byte, AH=vierde
aad  8Fh                        ; AL=(AL + 8Fh*AH) & FFh; AH=0
stosb
loop .decode
ret                             ; voer gereconstrueerde COM uit op 0100h

De eerste lodsw leest het twee-byte prefix van elke 'datagrafem' en negeert dit. De tweede lodsw leest vervolgens de 16-bit staart, die wordt omgezet in een 8-bit waarde met de magische constante 8Fh. De sleutel hier is een kenmerk van de aad-instructie van de 8088 waarmee deze een niet-decimale basis als immediate kan accepteren.

Natuurlijk werkt dit niet als lahf constant AH overschrijft, dus deze 17-byte decoder moet eerst zelf in het geheugen worden geconstrueerd. Dit kan worden bereikt met de eerder beschreven CamelWrite gadget. Het nadeel is dat de gecodeerde data slechts 25% efficiënt is, maar elk alternatief zou de complexiteit van de decoder en de code die deze genereert aanzienlijk verhogen.

Een VGA Emoji-demo

Kunnen we een basis VGA-demo maken met niets anders dan emoji? Met onze emoji-decoder is het vrij eenvoudig om een basis VGA-demo in te pakken, deze naar het geheugen te decoderen en er vervolgens naartoe te springen.

Hier is het volledige programma: 🐸☺️😖🐰😗😯😯😯😯😯😯😯😹😯<0xF0><0x9F><0x95><0xB3>️😯🐮🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐⭐️🍽️🍽️🍽️🍽️🐮🐰😔😬😬🗓️🍽️👁️📗🐪🗓️<0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAF>📗🐪🐮🗓️😿<0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>📗🐪🗓️🐮📗🐪🗓️<0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>👁️📗🐪🐮🗓️<0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>📗🐪🗓️😿<0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF><0xF0><0x9F><0xA7><0xAF>📗🐪🗓️😿🍽️🍽️🍽️🍽️🐮📗🐪🐮🗓️😯🍽️🍽️👁️📗🐪🐮🐮🐮🗓️😿<0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAE><0xF0><0x9F><0xA7><0xAE>📗🐪🗓️<0xF0><0x9F><0xA7><0xAE>👁️👁️🍽️👁️📗🐪🐰😔🐐🐐♿️🇹🇭⏪️✋️💕🐀🍥🐐📣🈚️🌌🌋🏐🌕️👻🌺🌻🍵🆙🌮🍝🌐🌋🍠🌋� 🍜💒🌳👹🎇👹🉑🎎🉑💞<0xF0><0x9F><0x86><0x96>🌳<0xF0><0x9F><0x86><0x8E>🎇👹🉑🎎🉑💞🐖👯<0xF0><0x9F><0x86><0x96>🌻🕕️🌿🐐🍙👺👽️🌳👹🎇💗🉑🎎🉑💞🖕🎎🌙👻🌺🌻🐻🎂🌻🌳👮🐖🐸🍤🕕️🌻🐠🐻🍝🌻🌳🌷🐎🌷🍭🌌💗👻🐖🐖🌜️🌛📛🍕🍓🍪🍷🌙🍘🍾🍪👻🌺🌻🌙🌘🌙🐗🌊🏐💗🎐<0xF0><0x9F><0xA7><0xAF>🔥🌉

Opgeslagen als een COM-bestand zou de bestandsgrootte 1092 bytes moeten zijn met een MD5-som van 9ed65cc927b257b113a298dee37215cc. Dit programma draait in elke versie van DOSBox.

Ik denk dat ik het concept naar tevredenheid heb bewezen — wat er nog te doen is, zou het creëren van een efficiëntere packer/decoder zijn, wellicht met gebruik van LZ4-compressie. Een COM2EMOJI utility zou vrij eenvoudig zijn, en misschien zelfs EXE2EMOJI.

Zou je een emoji BIOS kunnen bouwen? Een volledig emoji besturingssysteem? Zouden we EmojiDOOM kunnen hebben? Ik kijk uit naar de emoji-gebaseerde gruwelen die dit bericht over de wereld zal brengen.