Assembler och lågnivåprogrammering för x86-system · Lektion

Använda GDB för felsökning av Assembly

Bemästra GNU Debugger (GDB) för att sätta brytpunkter, inspektera register och minne samt stega genom Assembly-kod.

Lektion 1 av 412 steg

Använda GDB för felsökning av Assembly är en gratis lektion i Assembler och lågnivåprogrammering för x86-system på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Assembler och lågnivåprogrammering för x86-system, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Assembler och lågnivåprogrammering för x86-system innehåller totalt 4 lektioner.

Felsökningens bästa vän: GDB

Välkomna till felsökningens värld! När ni arbetar med lågnivåspråk som assembler är det avgörande att exakt förstå vad programmet gör, instruktion för instruktion.

GNU Debugger (GDB) är ett oerhört kraftfullt verktyg som låter er:

  • Pausa programmet vid specifika punkter (brytpunkter).
  • Stega genom koden rad för rad.
  • Kontrollera värdena i register och minne.
  • Förstå programmets flöde och identifiera problem.

Det är en oumbärlig färdighet för alla assemblerprogrammerare!

Förbereda assemblerkoden

Innan GDB kan hjälpa oss måste vi kompilera assemblerkoden med särskilda ”debug symbols”. Dessa symboler informerar GDB om variabelnamn, funktionsetiketter och källkodsrader, vilket gör felsökningen mycket enklare.

För NASM-assembler på Linux använder ni vanligtvis flaggan -g under kompilering och länkning:

  • Assemblera: nasm -f elf32 -g your_code.asm -o your_code.o
  • Länka: ld -m elf_i386 -g your_code.o -o your_executable

Flaggan -g bäddar in felsökningsinformationen direkt i objektfilen och den körbara filen.

Vårt mål: ett enkelt program

Vi använder ett enkelt assemblerprogram som mål för felsökningen. Programmet skriver ut ett meddelande i konsolen och utför sedan en enkel addition innan det avslutas.

Vi kompilerar det med felsökningssymboler och går sedan vidare till GDB.

; filename: debug_example.asm

section .data
    hello_msg db "Hello from Assembly!", 0xA ; Message to print
    hello_len equ $ - hello_msg

section .text
    global _start

_start:
    ; --- Part 1: Print "Hello from Assembly!" ---
    ; sys_write syscall (Linux x86 32-bit)
    mov eax, 4          ; syscall number for sys_write
    mov ebx, 1          ; file descriptor 1 (stdout)
    mov ecx, hello_msg  ; address of string to write
    mov edx, hello_len  ; length of string
    int 0x80            ; invoke kernel

    ; --- Part 2: Perform a simple calculation ---
    mov eax, 10         ; Move 10 into EAX
    mov ebx, 5          ; Move 5 into EBX
    add eax, ebx        ; Add EBX to EAX (EAX becomes 15)

    ; --- Part 3: Exit the program ---
    ; sys_exit syscall (Linux x86 32-bit)
    mov eax, 1          ; syscall number for sys_exit
    mov ebx, 0          ; exit code 0 (success)
    int 0x80            ; invoke kernel

Starta GDB

När programmet har kompilerats med felsökningssymboler är det enkelt att starta GDB. Öppna terminalen och skriv gdb följt av namnet på den körbara filen.

Om den körbara filen i vårt exempel heter debug_executable skriver ni:

gdb ./debug_executable

GDB läser in programmet och visar sin kommandoprompt, vanligtvis (gdb). Programmet körs inte ännu; GDB är bara redo att ta emot kommandon.

Ange den första brytpunkten

En brytpunkt är en markering som instruerar GDB att pausa programmets körning när det når en viss instruktion eller minnesadress. På så sätt stoppar ni programmet vid en intressant punkt.

För att ange en brytpunkt använder ni kommandot break eller b, följt av ett funktionsnamn, en etikett eller en minnesadress. För assembler använder vi ofta etiketter.

  • (gdb) break _start: Anger en brytpunkt vid programmets startpunkt.
  • (gdb) b *0x80480a0: Anger en brytpunkt vid en specifik minnesadress (exempeladress).

Köra och återuppta körningen

När ni har angett brytpunkter kan ni starta programmet eller återuppta körningen.

  • run (eller r): Startar programmet från början. Det körs tills det når den första brytpunkten, avslutas eller kraschar.
  • continue (eller c): Återupptar körningen efter att programmet har nått en brytpunkt. Det fortsätter tills nästa brytpunkt eller tills programmet avslutas.

Försök att ange en brytpunkt vid _start och använd sedan run. Då ser ni hur GDB pausar precis i början av programmet!

Stega genom körningen

När programmet har pausats vid en brytpunkt kan ni köra instruktionerna en i taget. Det är ovärderligt för att se den exakta effekten av varje instruktion.

  • stepi (eller si): Kör nästa enskilda instruktion. Om instruktionen är ett call till en procedur går si in i den proceduren.
  • nexti (eller ni): Kör nästa enskilda instruktion. Om instruktionen är ett call kör ni hela proceduren och stannar vid instruktionen direkt *efter* call.

Använd si för att noggrant följa varje instruktion, eller ni för att hoppa över proceduranrop som ni inte är intresserade av.

Titta på register

Register är processorns små, extremt snabba lagringsplatser. I assembler flyttar ni hela tiden data till och från dem. Med GDB kan ni granska deras aktuella värden.

  • info registers (eller i r): Visar de aktuella värdena för alla register för allmän användning, segmentregister, instruktionspekaren (EIP/RIP) och flaggorna.
  • info registers eax: Visar värdet för ett specifikt register, till exempel EAX.
  • print $eax: Ett annat sätt att skriva ut värdet för ett specifikt register. Prefixet $ talar om för GDB att det är ett register.

Efter instruktionen add eax, ebx kan ni kontrollera eax för att se det nya värdet (15).

Granska minnesinnehåll

Utöver register behöver ni ofta granska vad som finns lagrat i minnet. Kommandot x (examine) är användbart för detta.

Formatet är x/<count><format><unit-size> <address>:

  • count (N): Hur många enheter som ska visas.
  • format (F): Hur de ska visas (till exempel x för hexadecimalt, d för decimalt, s för sträng och i för instruktioner).
  • unit-size (U): Storleken för varje enhet (till exempel b för byte, h för halfword/2 byte, w för word/4 byte och g för giant/8 byte).

Exempel:

  • (gdb) x/s hello_msg: Visar strängen vid hello_msg.
  • (gdb) x/4xw $esp: Visar 4 word (4 byte vardera) i hexadecimal form med start från stackpekaren.

Demontera kod under körning

Ibland felsöker ni och behöver se assemblerinstruktionerna runt den aktuella körningspunkten. Kommandot disassemble (eller disas) omvandlar maskinkod tillbaka till assembler.

  • (gdb) disassemble: Demonterar funktionen som körs för närvarande.
  • (gdb) disas _start: Demonterar hela funktionen _start.
  • (gdb) disas $eip, +20: Demonterar 20 byte instruktioner med start från den aktuella instruktionspekaren (EIP).

Det hjälper er att snabbt orientera er och se sammanhanget i den omgivande koden.

GDB-kommandoutmaning

Vilka av följande GDB-kommandon används för att styra programmets körning (starta, pausa, återuppta och stega)?

Felsökningens kraft frigjord

Grattis! Ni har tagit era första steg mot att bemästra GDB för felsökning av assemblerkod. Vi gick igenom:

  • varför GDB är nödvändigt för programmering på låg nivå.
  • hur man kompilerar assemblerkod med felsökningssymboler.
  • grundläggande GDB-kommandon som run, break och continue.
  • hur man stegar genom kod med stepi och nexti.
  • hur man granskar register (info registers) och minne (x).
  • hur man disassemblerar kod under körning (disassemble).

Dessa grundläggande färdigheter hjälper er att förstå och felsöka komplexa assemblerprogram genom att avslöja hur de fungerar, instruktion för instruktion. Fortsätt öva!

Gratis att börja

Lär dig Assembly med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
12
Lektioner
48

Vanliga frågor

Är lektionen ”Använda GDB för felsökning av Assembly” gratis?

Ja – hela texten till ”Använda GDB för felsökning av Assembly” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Assembler och lågnivåprogrammering för x86-system, kan Ni uppgradera till CoddyKit PRO. Kursen i Assembler och lågnivåprogrammering för x86-system innehåller totalt 4 lektioner.

Vad lär jag mig i ”Använda GDB för felsökning av Assembly”?

Bemästra GNU Debugger (GDB) för att sätta brytpunkter, inspektera register och minne samt stega genom Assembly-kod. Ni övar på Assembler och lågnivåprogrammering för x86-system med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Assembler och lågnivåprogrammering för x86-system?

Du behöver inga förkunskaper. Utbildningen i Assembler och lågnivåprogrammering för x86-system på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Använda GDB för felsökning av Assembly”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Assembler och lågnivåprogrammering för x86-system-lektionen?

Ja. Varje Assembler och lågnivåprogrammering för x86-system-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Använda GDB för felsökning av Assembly
  2. Introduktion till disassembleringsverktyg
  3. Grundläggande reverse engineering-tekniker
  4. Dynamisk analys med tracing och hooking
← Tillbaka till Assembler och lågnivåprogrammering för x86-system