De basis van reverse-engineering en binaire analyse · Les

Inlining en lustransformaties herkennen

Herken hoe de compiler functies inline uitvoert en lussen herschrijft (unrolling, vectorization), zodat geoptimaliseerde assembly terug te voeren blijft op de bedoeling van de broncode.

Les 4 van 413 stappen

Inlining en lustransformaties herkennen is een gratis De basis van reverse-engineering en binaire analyse-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject De basis van reverse-engineering en binaire analyse. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus De basis van reverse-engineering en binaire analyse bevat in totaal 4 lessen.

Optimalisaties veranderen de structuur

Je kent veelvoorkomende optimalisaties, kunt geoptimaliseerde assembly lezen en logica reconstrueren. Twee transformaties veroorzaken de meeste verwarring: function inlining en loop reshaping.

Als je ze herkent, blijft je reconstructie nauwkeurig.

Wat is inlining?

Inlining vervangt een functieaanroep door de body van de aangeroepen functie, waardoor de overhead van de aanroep verdwijnt.

In het binaire bestand kan de oorspronkelijke functie volledig verdwijnen; de code ervan verschijnt samengevoegd in elke aanroeper.

// source
static int sq(int x){ return x*x; }
int f(int a){ return sq(a) + 1; }
// after inlining f becomes: return a*a + 1;

Geïnline-de code herkennen

Signalen van inlining:

  • Een helperfunctie die je als afzonderlijke functie verwacht, verschijnt nergens
  • Hetzelfde instructiepatroon wordt in veel aanroepers herhaald
  • Er staat geen overeenkomende call waar de broncode er wel een had

Loops uitrollen

Loop unrolling voert meerdere iteraties per loopdoorgang uit om de overhead van sprongen te verminderen.

Een loop die vier keer hoort uit te voeren, kan vier kopieën van de body tonen zonder interne sprong.

; sum 4 elements, unrolled
mov eax, [rdi]
add eax, [rdi+4]
add eax, [rdi+8]
add eax, [rdi+12]

Gedeeltelijk uitrollen

Bij een onbekend aantal iteraties rolt de compiler de loop uit in blokken (bijvoorbeeld vier tegelijk), plus een restloop voor de overgebleven iteraties.

Een groot blok gevolgd door een kleine loop met één stap per keer is de klassieke herkenning van gedeeltelijk uitrollen.

Vectorisatie (SIMD)

Vectorisatie verwerkt meerdere gegevenselementen tegelijk met SIMD-registers zoals XMM/YMM.

Instructies zoals movdqu, paddd of addps geven aan dat een scalaire loop is omgezet in vectorbewerkingen.

movdqu xmm0, [rsi]
paddd  xmm0, xmm1   ; add 4 ints in parallel
movdqu [rdi], xmm0

De oorspronkelijke loop reconstrueren

Wanneer je SIMD- of uitgerolde bodies ziet, vouw ze dan in gedachten terug tot één scalaire loop. Vier parallelle optellingen zijn gelijk aan een loop die vier elementen optelt.

Documenteer de eenvoudige bedoeling, niet de geoptimaliseerde vorm.

Loop-invariante codeverplaatsing

Compilers halen berekeningen die tijdens iteraties niet veranderen uit de loop. Een vermenigvuldiging die je in de loop verwacht, kan ervoor staan.

Als je dit weet, lees je niet verkeerd waar het werk wordt uitgevoerd.

Krachtvermindering

Vermenigvuldigingen in loops worden vaak vervangen door goedkopere optellingen (strength reduction). Een index maal een stapgrootte wordt een pointer die bij elke doorgang met die stapgrootte wordt verhoogd.

Herken add ptr, 8 als ‘volgend element’ en niet als letterlijke pointerrekenkunde.

Tools kunnen helpen

Decompilers (Ghidra, Hex-Rays) rollen loops vaak automatisch opnieuw uit en maken geïnline-de code weer afzonderlijk, zodat ze schonere pseudocode tonen. Gebruik ze, maar controleer de assembly wanneer het gedrag ertoe doet.

Optimalisatie van tail calls

Wanneer de laatste actie van een functie een aanroep is, kan de compiler die omzetten in een sprong in plaats van een aanroep gevolgd door een return, waarbij het huidige frame opnieuw wordt gebruikt.

Een jmp naar een andere functie aan het einde van een routine, in plaats van een call gevolgd door ret, is kenmerkend voor een tail call.

; tail call instead of call + ret
mov edi, eax
jmp helper

Korte controle

Je verwachtte een kleine helperfunctie, maar die verschijnt nooit als eigen routine; in plaats daarvan wordt de code ervan in elke aanroeper gekopieerd. Om welke optimalisatie gaat het?

Samenvatting

Je kunt nu door ingrijpende optimalisaties heen kijken:

  • Inlining voegt aangeroepen functies samen met hun aanroepers
  • Uitrollen en vectorisatie verdelen loop-bodies over parallel werk
  • Verplaatsing van invariante code en krachtvermindering verplaatsen bewerkingen of maken ze goedkoper

Vouw deze in je reconstructie terug naar de eenvoudige bedoeling van de broncode.

Gratis beginnen

Leer Assembly met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
12
Lessen
48

Veelgestelde vragen

Is de les “Inlining en lustransformaties herkennen” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad De basis van reverse-engineering en binaire analyse, waaronder “Inlining en lustransformaties herkennen”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus De basis van reverse-engineering en binaire analyse bevat in totaal 4 lessen.

Wat leer ik in “Inlining en lustransformaties herkennen”?

Herken hoe de compiler functies inline uitvoert en lussen herschrijft (unrolling, vectorization), zodat geoptimaliseerde assembly terug te voeren blijft op de bedoeling van de broncode. Je oefent met De basis van reverse-engineering en binaire analyse door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met De basis van reverse-engineering en binaire analyse te beginnen?

Ervaring vooraf is niet nodig. De basis van reverse-engineering en binaire analyse op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Inlining en lustransformaties herkennen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over De basis van reverse-engineering en binaire analyse?

Ja. Elke les over De basis van reverse-engineering en binaire analyse bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Gangbare compileroptimalisaties
  2. Geoptimaliseerde assembly analyseren
  3. Oorspronkelijke programmalogica reconstrueren
  4. Inlining en lustransformaties herkennen
← Terug naar De basis van reverse-engineering en binaire analyse