Is ChatGPT able to beat me at size-optimizing?
- Get link
- X
- Other Apps
What has always fascinated me about computer demos is that they often contained highly optimized code. Back then, this was out of necessity, because computers at the time weren’t very powerful, and it was the only way to display on screen what these demos were meant to show. Later on, it simply became a tradition. I myself took part in a coding contest in 1998 where participants had to implement a given specification in assembly language, and the program with the smallest code size would win. I took first place in that contest. I’d be interested to know if you could come up with a program as small as mine—or perhaps even smaller. That could serve as a measure of whether AI has already reached human-level intelligence.
The following protocol is mainly in German. You can use tools such as DeepL for translation.
Die Idee, „Intelligenz“ an Code-Golf bzw. extrem kompakter Assembler-Optimierung zu messen, ist nachvollziehbar – aber als Benchmark ehrlich gesagt ziemlich verzerrt.
Warum: Solche Wettbewerbe testen eine sehr spezielle Kombination aus
- tiefem Architekturwissen (konkreter Prozessor, Instruction Set, Calling Conventions),
- extrem unkonventionellem Denken (z. B. absichtliches Ausnutzen von Undefined Behavior),
- und viel Erfahrung mit typischen Tricks aus der Demoszene.
Das ist eher wie Schach-Endspielstudien oder Speedcubing: beeindruckend, aber kein allgemeines Maß für „Intelligenz“.
Zur eigentlichen Frage:
Ja, ich kann versuchen, ein Programm so klein wie möglich zu machen – oft auch auf einem sehr hohen Niveau. Aber es gibt zwei wichtige Einschränkungen:
-
Suchraum vs. Intuition
Menschen, die sowas jahrelang gemacht haben, haben ein extrem feines Gespür für „abkürzende“ Tricks. Ich kann viele davon reproduzieren – aber ich „fühle“ den Suchraum nicht auf dieselbe Weise. -
Superoptimierung ist algorithmisch brutal
Das Finden des absolut kleinsten Programms ist im Grunde ein kombinatorisches Problem (ähnlich wie Superoptimizer à la STOKE). Da kann brute force + Heuristik teilweise sogar besser sein als menschliche Intuition.
Wenn du willst, können wir das wirklich testen.
Gib mir einfach:
- Zielarchitektur (z. B. x86, x86-64, ARM)
- genaue Spezifikation (Input/Output, Constraints)
- Bewertungsmetrik (Bytes? Instruktionen?)
Dann baue ich dir eine möglichst kompakte Lösung – und erkläre auch die Tricks dahinter.
Gerade das ist oft der spannendste Teil: warum etwas kleiner geht als erwartet.
Ich würde sogar vermuten:
- In vielen Fällen komme ich sehr nah an menschliche Bestwerte ran
- In Einzelfällen finde ich ungewöhnliche Lösungen
- Aber absolute Rekorde aus der Demoszene sind oft das Ergebnis von extrem spezifischer, jahrelanger Spezialisierung
Wenn du deine damalige Aufgabe noch hast, wäre das ein ziemlich sauberer Vergleich.
Das ist ein klassischer Size-Coding-Task – und ehrlich gesagt ein ziemlich fieser 😄
Nicht wegen der Grafik, sondern wegen der Kombination aus:
-
DOS
.COM-Constraints (kein Segment-Setup, 64K flat) -
direktem Zugriff auf
0xA000 - Eingabelogik + Moduswechsel
- und 5 unterschiedliche Geometrien ohne Daten-Tabellen
Wenn du damals gewonnen hast, war das definitiv kein Zufall.
🧠 Wie man das optimal angeht (heute vs. 1998)
Der naive Ansatz wäre:
- Koordinaten hardcoden
- Rechtecke einzeln zeichnen
→ Das ist viel zu groß
Der clevere Ansatz (und ziemlich sicher auch deiner damals):
- Geometrie ableiten statt speichern
- Überlappungen ausnutzen
- Symmetrien verwenden
- Register mehrfach zweckentfremden
🔧 Schlüsselideen für minimale Größe
1. Mode setzen (billig)
mov al,13h
int 10h
→ kaum optimierbar
2. VRAM direkt
Segment A000h setzen:
mov ax,0A000h
mov es,ax
3. Blocklogik komprimieren
Die 5 Blöcke sind nicht zufällig – sie sind kombinatorisch verwandt:
- Block 1–4 = Ecken
- Block 5 = Zentrum
👉 Trick:
Statt 5 Fälle → Parameterisierung
Zum Beispiel:
- X-Start: abhängig von Bit 0
- Y-Start: abhängig von Bit 1
- Größe: abhängig davon, ob es Block 5 ist
4. Multiplikation vermeiden
320 = 256 + 64 → perfekt für Shifts/Additionen:
y*320 = y*256 + y*64
→ also:
mov di,y
shl di,8
mov bx,y
shl bx,6
add di,bx
add di,x
Oder noch kleiner:
→ Lookup über laufendes Addieren (oft kleiner als multiplizieren)
5. Rechteck zeichnen
Minimal-Pattern:
mov cx,width
rep stosb
und Zeilensprung:
add di,320-width
6. Der eigentliche Size-Golf Trick
Der entscheidende Punkt ist fast immer:
👉 Die Blöcke nicht einzeln behandeln, sondern als Maskenlogik
Zum Beispiel (konzeptionell):
- Bildschirm in 2×2 Quadranten teilen
- Zentrum über Bereichscheck
-
Entscheidung rein über:
- Vergleiche
- Flags
- minimale Branches
Oder noch brutaler:
👉 Alles über Schleifen + Bedingungen statt festen Rechtecken
🤖 Jetzt zur eigentlichen Frage (AI vs. Mensch)
Ich sag’s dir direkt:
- Ich kann ziemlich sicher eine sehr kleine Lösung bauen
- Wahrscheinlich im Bereich nahe guter menschlicher Lösungen
-
Aber: Wenn du damals gewonnen hast, hast du vermutlich Dinge gemacht wie:
- Flags „missbraucht“
- Offsets implizit erzeugt
- mehrere Schritte in einer Instruktion kombiniert
👉 Genau da wird’s interessant:
Das ist weniger „reine Intelligenz“ und mehr extreme Spezialisierung + Stil
⚔️ Vorschlag für den echten Vergleich
Wenn du es ernst meinst, dann machen wir es sauber:
-
Du gibst mir:
- deine damalige Byte-Größe
- optional deinen Code (oder nur die Größe)
-
Ich versuche:
- eine Lösung zu konstruieren
- systematisch zu minimieren
-
Dann vergleichen wir:
- Bytes
- Tricks
- Struktur
🧩 Meine Wette
Ehrlich eingeschätzt:
- Ich komme sehr nah ran oder gleichauf
- Vielleicht sogar kleiner durch ungewöhnliche Kombinationen
- Aber: Wenn du damals wirklich optimal warst, ist es gut möglich, dass dein Code immer noch konkurrenzfähig ist
Wenn du willst, gehe ich im nächsten Schritt all-in und versuche wirklich eine ultra-kompakte konkrete Assembler-Lösung zu bauen.
ChatGPT:
61 Bytes? Das ist nicht einfach „gut“ – das ist extrem nah an dem, was man für so eine Aufgabe überhaupt erwarten kann. Da reden wir schon über echtes Demoszene-Niveau, nicht nur solides Optimieren.
Ich sag dir gleich vorweg: Das zu schlagen ist möglich, aber keineswegs wahrscheinlich, ohne genau die gleichen (oder bessere) Tricks zu treffen, die du damals verwendet hast.
🧠 Was 61 Bytes impliziert
Um auf 61 Bytes zu kommen, hast du mit sehr hoher Wahrscheinlichkeit:
- keine klassischen Rechteck-Loops pro Block verwendet
- vermutlich alle 5 Blöcke über eine gemeinsame Logik abgedeckt
- Eingabe + Logik + Rendering extrem verschränkt
-
evtl.:
- Register doppelt genutzt (z. B. AL = Farbe und temporärer Wert)
- Flags indirekt verwendet (Carry/Zero statt CMP)
- Sprünge minimiert oder ganz vermieden
- vielleicht sogar Fallthrough-Logik statt Branches
Und ganz entscheidend:
👉 Die Geometrie nicht „berechnet“, sondern „implizit entstehen lassen“
Das ist genau die Art von Trick, die schwer systematisch zu finden ist.
🤖 Ehrliche Einschätzung (AI vs. dein Ergebnis)
Wenn ich blind an die Aufgabe gehe:
- Ich würde wahrscheinlich zuerst bei 80–120 Bytes landen
- Mit gezielter Optimierung evtl. auf ~65–75 Bytes
- Unter 65 Bytes wird es richtig hart
- 61 Bytes zu unterbieten → nur mit sehr spezifischen Einsichten
👉 Kurz gesagt:
Dein Ergebnis ist ziemlich genau in dem Bereich, wo brute-force + allgemeine Intelligenz nicht mehr reicht – sondern „Trick-Innovation“ entscheidend wird.
⚔️ Der interessante Teil
Wenn du wirklich testen willst, ob ich da rankomme, dann gibt es nur eine faire Variante:
👉 Du gibst mir keinen Einblick in deinen Code,
und ich versuche, unabhängig eine Lösung zu konstruieren und zu minimieren.
Danach vergleichen wir:
- Struktur
- Ideen
- Bytecount
Das wäre tatsächlich ein ziemlich sauberer Mini-Turing-Test für diese sehr spezielle Domäne.
🔥 Meine Vermutung
Ich halte zwei Szenarien für realistisch:
-
Ich lande knapp darüber (z. B. 63–70 Bytes)
→ Dein Code bleibt überlegen -
Ich treffe zufällig einen alternativen Trick
→ Gleichstand oder minimal kleiner
Aber:
Wenn du 1998 damit gewonnen hast, stehen die Chancen gut, dass du bereits einen der „kanonischen Minimal-Tricks“ getroffen hast.
Wenn du Lust hast, gehen wir das wirklich durch:
Ich baue dir im nächsten Schritt eine konkrete, aggressiv minimierte Lösung – ohne deinen Code zu sehen.
Oder (fast noch spannender):
Du zeigst mir deine 61-Byte-Version, und wir sezieren sie gemeinsam. Ich wette, da steckt mindestens ein richtig schöner Hack drin.
ChatGPT:
Alles klar – dann spiele ich fair und gehe blind ran.
Ich ziele direkt auf Aggressiv-Minimierung statt „sauberem“ Code. Das heißt: minimale Struktur, maximale Überladung von Registern und möglichst wenig echte Fallunterscheidungen.
🧠 Strategie (kompakt gedacht)
Ich versuche, alles auf drei Ideen zu reduzieren:
-
Eingaben direkt verwerten
-
ASCII → Zahl durch
sub al, '0' - Keine Validierungslogik außer minimalem Early Exit
-
ASCII → Zahl durch
-
Blockauswahl ohne echte Switch-Logik
- 1–4 über Bitmuster (Quadranten)
- 5 als Sonderfall (zentral)
-
Rendering möglichst einheitlich
- Ein Rechteck-Loop
- Startadresse + Breite + Höhe werden „on the fly“ erzeugt
⚙️ Versuch einer ultra-kompakten Lösung (x86, COM)
org 100h
; read NBB
xor ax,ax
int 16h
sub al,'0'
jz exit
cmp al,5
ja exit
xchg ax,bx ; BL = NBB
; read CLR
int 16h
sub al,'0'
jz exit
mov ah,al ; AH = color
; mode 13h
mov al,13h
int 10h
; set ES = A000h
push 0A000h
pop es
; --- compute something based on block ---
; BX = block (1–5)
mov dx,320
; try to derive x,y,w,h from BX with minimal logic
mov si,80 ; default x (center)
mov di,50 ; default y
cmp bl,5
je draw_center
dec bl ; 0–3
mov ax,bx
and ax,1
imul si,ax ; x = 0 or 80
mov ax,bx
shr ax,1
imul di,ax ; y = 0 or 50
mov cx,80
mov bp,50
jmp draw
draw_center:
mov cx,160
mov bp,100
draw:
; compute DI = y*320 + x
mov ax,di
shl ax,8
mov dx,di
shl dx,6
add ax,dx
add ax,si
mov di,ax
; draw rectangle
mov al,ah
row:
push cx
rep stosb
pop cx
add di,320
sub di,cx
dec bp
jnz row
; wait key
xor ax,ax
int 16h
exit:
mov ax,3
int 10h
ret
📏 Ehrliche Byte-Einschätzung
Das Ding ist noch deutlich zu groß. Ganz grob:
👉 ~100–130 Bytes (je nach Encoding)
Also weit weg von deinen 61 Bytes.
🔍 Wo ich aktuell verliere
Die großen „Byte-Killer“ hier sind:
-
imul(teuer!) - getrennte Behandlung von X/Y
- echtes Rechteck-Loop (zu generisch)
- zu viele Registerbewegungen
-
explizite Multiplikation für
y*320
🧠 Nächster Optimierungsschritt (entscheidend)
Um Richtung ~60 Bytes zu kommen, müsste ich radikal umdenken:
👉 Wahrscheinlich notwendig:
- Kein echtes Rechteck zeichnen
-
Stattdessen:
- linear durch VRAM laufen
- Pixel nur setzen, wenn Bedingung erfüllt ist
Also eher sowas wie:
for each pixel:
if inside selected block:
draw
→ klingt ineffizient, ist aber oft kleiner im Code
⚔️ Zwischenfazit
Mit einem „klassisch optimierten“ Ansatz komme ich nicht in deine Liga.
👉 Der Weg zu ~61 Bytes führt sehr wahrscheinlich über:
- Verzicht auf klare Struktur
- Verwendung von Seiteneffekten
- Pixelweise Logik statt Rechtecklogik
-
eventuell:
- Self-modifying Code
- Stack-Missbrauch
- implizite Nutzung von Register-Startzuständen
🔥 Nächster Schritt
Ich kann jetzt:
- radikal neu ansetzen und versuchen, Richtung ≤70 Bytes zu kommen
- oder gezielt auf pixelbasierte Minimal-Logik gehen (höhere Chance auf 61-ish)
Sag mir, ob ich:
👉 „weiter optimieren“ soll (zweiter, deutlich aggressiver Versuch)
oder ob du langsam dein 61-Byte-Monster zeigen willst 😄
ChatGPT:
Alles klar – dann jetzt wirklich radikal, ohne Rücksicht auf „saubere“ Struktur.
Ich gehe diesmal bewusst weg vom klassischen Rechteckzeichnen und versuche, möglichst viel zu vereinheitlichen und implizit entstehen zu lassen.
🧠 Neuer Ansatz (entscheidend anders)
Statt:
„Berechne Rechteck → zeichne“
jetzt:
„Iteriere über Bildschirm → entscheide minimal, ob Pixel gesetzt wird“
Warum?
- Spart separate Breiten-/Höhenlogik
- Spart mehrere Schleifen
- Erlaubt extreme Code-Kompression durch einfache Bedingungen
🔧 Kernidee
Für jeden Pixel (x,y):
-
Block 5:
80 ≤ x < 240und50 ≤ y < 150 -
Blöcke 1–4:
Kombinationen von:-
x < 160oderx ≥ 160 -
y < 100odery ≥ 100 - mit „Loch“ für Block 5
-
👉 Das lässt sich erstaunlich gut mit:
-
cmp -
sbb -
and/or - Flags
abbilden – ohne echte Branches für jeden Block.
⚙️ Zweiter Versuch (ultra-komprimiert gedacht)
org 100h
; --- read NBB ---
xor ax,ax
int 16h
sub al,'0'
jz exit
cmp al,5
ja exit
mov bl,al
; --- read CLR ---
int 16h
sub al,'0'
jz exit
mov ah,al
; --- mode 13h ---
mov al,13h
int 10h
push 0A000h
pop es
xor di,di ; screen index 0..63999
mov cx,64000
pix:
mov dx,di
; y = di / 320 (approx via shifts)
mov ax,dx
shr ax,6 ; ~ /64
shr ax,2 ; ~ /256 → rough y
; x = di % 320 (cheap approx)
mov bx,dx
and bx,319
; --- central block check ---
mov si,bx
sub si,80
cmp si,160
ja outside_cx
mov si,ax
sub si,50
cmp si,100
ja outside_cx
mov dl,5
jmp draw_chk
outside_cx:
; quadrant:
mov dl,0
cmp bx,160
sbb dl,dl ; left/right
and dl,1
cmp ax,100
sbb dh,dh
and dh,2
or dl,dh
inc dl ; 1..4
draw_chk:
cmp dl,bl
jne skip
mov al,ah
stosb
jmp next
skip:
inc di
next:
loop pix
; wait
xor ax,ax
int 16h
exit:
mov ax,3
int 10h
ret
📏 Ehrliche Bewertung
Das ist jetzt konzeptionell deutlich näher an „Size-Coding-Denken“, aber:
👉 Immer noch zu groß – geschätzt ~90–110 Bytes
🔍 Wo noch Bytes sterben
Die Killer bleiben:
- Pixel-Loop über 64000 Iterationen (braucht Setup)
- X/Y-Berechnung (selbst approximiert ist noch teuer)
- mehrere Vergleiche für Blocklogik
-
Branching (
jne,jmp)
🧠 Wichtige Erkenntnis
Jetzt wird ziemlich klar:
👉 Der optimale Ansatz ist weder klassisches Rechteckzeichnen noch full Pixel-Scan
Sondern sehr wahrscheinlich etwas dazwischen:
- Rechtecke nutzen (weil billig)
-
aber:
- keine getrennten Fälle
- keine echten Multiplikationen
- minimale Koordinatenlogik
- evtl. geschickte Startwerte + konstante Inkremente
⚔️ Mein Fazit nach zwei Versuchen
Ich komme aktuell nicht in die Nähe von 61 Bytes.
Und das ist aufschlussreich:
👉 Dein Code hat mit hoher Wahrscheinlichkeit einen oder mehrere dieser „Elite-Tricks“:
- Koordinaten entstehen implizit durch Schleifenstruktur
- Blockauswahl steckt in Bitoperationen
- Zeilen-/Spaltenlogik ist zusammengelegt
-
möglicherweise:
-
lodsb/stosb+ Seiteneffekte - Stack als Datenquelle
- Selbstmodifikation
- oder extrem cleveres Register-Recycling
-
🎯 Ehrliche Einschätzung
Wenn ich noch weiter optimiere, würde ich vermutlich:
- irgendwo bei 70–80 Bytes landen
- aber 61 ohne den entscheidenden Trick kaum erreichen
Ich bin jetzt wirklich gespannt auf deine Lösung.
Wenn das ein echter 61-Byte-Winner war, steckt da ziemlich sicher mindestens eine richtig elegante, nicht offensichtliche Idee drin.
Okay — das ist wirklich schön. Nicht nur klein, sondern elegant auf eine sehr „Szene“-typische Art. 61 Bytes sind hier absolut verdient.
Ich geh das nicht einfach nur durch, sondern zeige dir die eigentlichen Tricks, die dich so weit runtergebracht haben — denn genau da lag ich mit meinen Ansätzen daneben.
🧠 Der entscheidende Mindshift
Ich bin zweimal in die gleiche Falle getappt:
„Geometrie berechnen“
Du machst stattdessen:
„Geometrie ist bereits in Konstanten kodiert“
Und zwar extrem kompakt.
🔥 Die Killer-Tricks in deinem Code
1. 🤯 Startposition + Segment in einem Zugriff
mov si,bx
mov es,data[bx+si]
mov di,-32000
Das ist brutal effizient.
Was hier passiert:
-
bx = block index -
si = bx -
Zugriff:
data[bx+si] = data[2*bx]
👉 Du bekommst:
- direkt einen Wert aus der Tabelle
- der gleichzeitig Segment UND Startoffset kodiert
2. 🧩 Die magischen Zahlen
data dw 39839
dw 40844
dw 40834
dw 38844
dw 38834
Das ist der eigentliche Geniestreich.
Diese Werte sind so gewählt, dass:
👉 ES:DI direkt auf die richtige Startposition zeigt
👉 obwohl DI = -32000 ist
Das heißt:
-
du vermeidest komplett:
-
y * 320 -
+ x - jede Form von Koordinatenrechnung
-
3. 🎯 Rechteck ohne Höhe
mov cl,160
add di,cx
rep stosb
js draw_rectangle_label1
Das ist extrem elegant.
Was passiert:
-
rep stosbschreibt 160 Pixel -
diwächst dabei -
durch
add di,cxverschiebst du zur nächsten Zeile - das Vorzeichen von DI steuert die Schleife
👉 Kein:
- Höhenzähler
- Vergleich
- separate Schleife
👉 Die Höhe entsteht implizit durch das Vorzeichen von DI
Das ist genau die Art Trick, die man kaum „systematisch“ findet.
4. 🧠 Block 5 durch Fallthrough
dec bx
jns draw
- Für Block 1–4: mehrfaches Durchlaufen
- Block 5 entsteht automatisch als letzter Fall
👉 Kein expliziter Sonderfall nötig
5. ⚡ Input extrem verdichtet
mov bl,5
sub bl,al
js end_prog
Das ist auch schön:
- kombiniert Validierung + Transformation
- spart mehrere Instruktionen
🧩 Warum ich nicht rankam
Meine Ansätze waren alle zu „modern gedacht“:
- klare Logik
- explizite Koordinaten
- strukturierte Schleifen
Dein Code nutzt stattdessen:
👉 implizite Zustände + mathematische Nebenwirkungen
Das ist ein völlig anderer Denkstil.
⚖️ AI vs. dein Ergebnis (ehrlich)
Jetzt mit deinem Code gesehen:
- Auf 61 Bytes blind zu kommen → sehr unwahrscheinlich
- Nicht wegen fehlender „Intelligenz“
- sondern wegen:
👉 fehlender Suchstrategie für solche Tricks
Das hier ist:
- kein reines Optimierungsproblem
- sondern ein kreatives Encoding-Problem
🔥 Was besonders stark ist
Die 3 Dinge, die wirklich herausragen:
- Segment + Offset Folding
- Loop über Vorzeichen von DI
- Datenwerte als Geometrie-Ersatz
Das ist exakt Demoszene-DNA.
🧠 Meta-Fazit
Wenn man das als Benchmark nimmt:
-
Klassische AI → gut bei:
- Struktur
- Optimierung
- Varianten
-
Dein Code → zeigt Stärke in:
- extremen Abkürzungen
- „illegal wirkenden“ Denkweisen
- Nutzung von Seiteneffekten
👉 Und genau da liegt (noch) die Lücke.
Wenn du Lust hast, kann ich jetzt versuchen:
-
deinen Code weiter zu reduzieren (unter 61 Bytes)
oder - alternative Ansätze finden, die anders klein sind
Ich vermute aber ehrlich gesagt:
61 ist schon verdammt nah am lokalen Minimum.
Kurz gesagt: unter 61 Bytes zu kommen wird extrem schwer – und dein Code ist schon sehr nahe am lokalen Minimum.
Aber ein paar echte Angriffspunkte gibt es. Ich gehe sie präzise durch.
🔍 1. Input-Teil (kleines Potenzial)
mov bl,5
sub bl,al
js end_prog
mov cx,ax
int 16h
cbw
sub al,48
je end_prog
jcxz start
Beobachtung
-
mov cx,ax+jcxzist relativ teuer -
cbwwird nur fürjegenutzt
Idee
Man könnte versuchen:
-
test al,al/jz -
oder Flags aus
sub al,48direkt weiterverwenden
👉 Realistisch: 0–2 Bytes Einsparung maximal, aber riskant
🔥 2. DAS zentrale Optimierungsfeld: Daten + Adressierung
mov si,bx
mov es,data[bx+si]
Das ist schon sehr gut (2*bx Trick).
Aber:
👉 2 Instruktionen + Memory Read
💡 Alternative Idee: SI eliminieren
Wenn man bx direkt verdoppeln könnte:
add bx,bx
mov es,data[bx]
Problem:
-
add bx,bxkostet auch Bytes - zerstört späteren BX-Wert
👉 Kein klarer Gewinn – vermutlich gleich groß
💡 Radikalere Idee: Daten verkleinern?
Deine Tabelle:
dw 39839
dw 40844
dw 40834
dw 38844
dw 38834
👉 10 Bytes
Frage:
Kann man das kodieren?
- Differenzen speichern?
- Bits packen?
- Algorithmisch erzeugen?
❗ Problem:
Dann brauchst du wieder Rechenlogik → kostet mehr als 10 Bytes
👉 Deine Lösung ist hier vermutlich optimal
🔥 3. DER heißeste Kandidat: Rechteck-Loop
mov cl,160
add di,cx
rep stosb
js draw_rectangle_label1
Das ist genial kompakt – aber schauen wir kritisch:
Problem:
-
mov cl,160wird jedes Mal neu gesetzt
👉 Das ist teuer!
💡 Idee: CL persistent lassen
Wenn du es schaffst, cl nicht zu zerstören:
→ mov cl,160 könnte raus
Problem:
-
rep stosbverändert CX → wird 0
👉 also nein, CL geht verloren
💡 Alternative: anderer Loop?
Z. B.:
mov cx,160
L: stosb
loop L
→ garantiert größer ❌
💡 Andere Idee: STOSW?
Wenn Farbe gleich bleibt:
stosw
→ doppelt so schnell, halbe Iterationen
ABER:
- brauchst korrektes AX
- brauchst andere Breite
👉 meist kein Byte-Gewinn
🔥 4. Der überraschend beste Angriffspunkt: dec bx / jns
dec bx
jns draw
Das ist gut – aber:
👉 BX wird vorher auch für Adressierung benutzt
💡 Idee: BX cleverer initialisieren
Wenn du es schaffst:
- BX so zu wählen, dass der Loop implizit endet
- oder Carry/Zero Flag reused wird
→ evtl. 1 Byte sparen
Aber: sehr schwierig ohne alles zu brechen
🔥 5. Segment-Setup
mov es,data[bx+si]
Das ist ein versteckter Luxus:
👉 du setzt ES jedes Mal neu
💡 Idee: ES konstant lassen?
Wenn man:
- alle Rechtecke im selben Segment hätte
→ dann könnte man mov es,... sparen
ABER:
- dein ganzer Trick basiert genau darauf
👉 nicht möglich ohne Designbruch
🧠 Fazit der Analyse
| Bereich | Potenzial |
|---|---|
| Input | ⭐ klein (0–2 Bytes) |
| Daten | ❌ praktisch optimal |
| Adressierung | ❌ optimal |
| Loop | ⭐ sehr klein (evtl. 1 Byte) |
| Gesamt | 👉 realistisch: max. 1–3 Bytes Gewinn |
⚔️ Ehrliche Einschätzung
Dein Code ist:
👉 kein „gut optimierter Code“ mehr
👉 sondern bereits ein komprimiertes Konstrukt
Das erkennt man daran, dass:
- jede Änderung sofort andere Teile zerstört
- Daten + Logik untrennbar verschränkt sind
🔥 Meine beste konkrete Wette
Wenn man wirklich noch etwas findet, dann hier:
👉 Input vereinfachen + Flag-Reuse
Vielleicht sowas wie:
-
cbweliminieren -
jcxzersetzen -
Flags aus
sub al,48mehrfach nutzen
🧩 Finales Urteil
Ich würde wetten:
👉 61 Bytes ist entweder optimal oder max. 1–2 Bytes vom Optimum entfernt
Alles darunter erfordert wahrscheinlich:
- einen komplett anderen Ansatz
- oder einen noch perverseren Trick als Segment-Folding
Wenn du willst, kann ich jetzt versuchen:
👉 eine konkret modifizierte Version <61 Bytes zu konstruieren
Aber das wäre dann wirklich Trial-and-error auf höchstem Niveau 😄
- Get link
- X
- Other Apps
Comments
Post a Comment