DECOMPILATION LABORATORY

10 Soal ASM ke C

5 Soal 32-bit (x86) dan 5 Soal 64-bit (x64) standar ujian UTS. Setiap soal dilengkapi analisis langkah demi langkah dari nol (identifikasi offset lokal, bukan menebak nama), visualisasi tabel stack memory, dan rekonstruksi kode bahasa C final.

01
Soal 1: Aritmetika Sederhana & Deklarasi Variabel (x86 32-bit)
Tipe: Aritmetika Dasar • Arsitektur: IA-32 Intel Syntax
x86 Assembly (32-bit)
push    ebp
mov     ebp, esp
sub     esp, 16
mov     DWORD PTR [ebp-4], 15
mov     DWORD PTR [ebp-8], 25
mov     edx, DWORD PTR [ebp-4]
mov     eax, DWORD PTR [ebp-8]
add     eax, edx
mov     DWORD PTR [ebp-12], eax
mov     eax, DWORD PTR [ebp-12]
leave
ret

Langkah 1: Identifikasi Prolog & Alokasi Memori Stack

Instruksi push ebp; mov ebp, esp membentuk basis stack frame baru. Instruksi sub esp, 16 memesan memori 16 byte pada stack untuk variabel lokal.

Langkah 2: Tracking Offset Stack & Nilai

Offset Relatif (Address)UkuranNilai Saat IniInferensi Variabel C
[ebp - 4]4 Byte (DWORD)15 (0x0000000F)int a = 15;
[ebp - 8]4 Byte (DWORD)25 (0x00000019)int b = 25;
[ebp - 12]4 Byte (DWORD)a + b = 40 (0x00000028)int c = a + b;
[ebp]4 ByteSaved EBPFrame Pointer Caller

Langkah 3: Analisis Instruksi Body & Epilog

  • mov edx, [ebp-4] menyalin nilai 15 ke EDX.
  • mov eax, [ebp-8] menyalin nilai 25 ke EAX.
  • add eax, edx menghitung 25 + 15 = 40, disimpan di EAX.
  • mov [ebp-12], eax menyimpan hasil penjumlahan ke [ebp-12].
  • mov eax, [ebp-12] memuat hasil ke EAX sebagai return value sebelum leave; ret.

Kode C Final:

C Code
int soal1() {
    int a = 15;
    int b = 25;
    int c = a + b;
    return c;
}
02
Soal 2: Percabangan Kondisional If-Else (x86 32-bit)
Tipe: Control Flow (CMP & JLE) • Arsitektur: IA-32
x86 Assembly (32-bit)
push    ebp
mov     ebp, esp
sub     esp, 16
mov     DWORD PTR [ebp-4], 10
mov     DWORD PTR [ebp-8], 20
mov     eax, DWORD PTR [ebp-4]
cmp     eax, DWORD PTR [ebp-8]
jle     .L2
mov     DWORD PTR [ebp-12], 100
jmp     .L3
.L2:
mov     DWORD PTR [ebp-12], 200
.L3:
mov     eax, DWORD PTR [ebp-12]
leave
ret

Langkah 1: Analisis Offset Variabel

Offset RelatifNilai AwalInferensi Variabel C
[ebp - 4]10int x = 10;
[ebp - 8]20int y = 20;
[ebp - 12]Uninitialized (Nantinya 100 atau 200)int result;

Langkah 2: Evaluasi Alur Kontrol Percabangan

  • mov eax, [ebp-4] : memuat x ke EAX.
  • cmp eax, [ebp-8] : membandingkan x dengan y (operasi x - y).
  • jle .L2 : Jump if Less or Equal (jika x <= y, lompat ke label .L2).
  • Jika kondisi x <= y SALAH (artinya x > y), alur berlanjut: result = 100; lalu jmp .L3 (melewati blok else).
  • Di label .L2: result = 200;.
  • Di label .L3: Mengembalikan result melalui EAX.

Kode C Final:

C Code
int soal2() {
    int x = 10;
    int y = 20;
    int result;
    if (x > y) {
        result = 100;
    } else {
        result = 200;
    }
    return result;
}
03
Soal 3: Perulangan While Loop (x86 32-bit)
Tipe: Looping • Arsitektur: IA-32
x86 Assembly (32-bit)
push    ebp
mov     ebp, esp
sub     esp, 16
mov     DWORD PTR [ebp-4], 1
mov     DWORD PTR [ebp-8], 10
jmp     .L_COND
.L_BODY:
mov     eax, DWORD PTR [ebp-4]
add     eax, eax
mov     DWORD PTR [ebp-4], eax
.L_COND:
cmp     DWORD PTR [ebp-4], 100
jle     .L_BODY
mov     eax, DWORD PTR [ebp-4]
leave
ret

Langkah 1: Identifikasi Pola Perulangan (Jump to Condition)

Pola compiler GCC standar saat mengoptimasi perulangan: inisialisasi variabel, lompat langsung ke pengecekan kondisi (jmp .L_COND). Jika kondisi terpenuhi (jle .L_BODY), ulangi tubuh loop.

Offset RelatifNilai AwalInferensi Variabel C
[ebp - 4]1int n = 1;
[ebp - 8]10Variabel tidak digunakan (dead code/unused int dummy = 10;)

Langkah 2: Operasi di dalam Body Loop

add eax, eax : menggandakan nilai EAX (ekuivalen n = n * 2 atau n += n).

Kondisi keluar: loop berjalan selama n <= 100.

Kode C Final:

C Code
int soal3() {
    int n = 1;
    while (n <= 100) {
        n = n * 2; // atau n += n;
    }
    return n;
}
04
Soal 4: Perulangan For Loop Akumulasi Total (x86 32-bit)
Tipe: For Loop & Accumulator • Arsitektur: IA-32
x86 Assembly (32-bit)
push    ebp
mov     ebp, esp
sub     esp, 16
mov     DWORD PTR [ebp-4], 0        ; total = 0
mov     DWORD PTR [ebp-8], 1        ; i = 1
jmp     .L_FOR_TEST
.L_FOR_BODY:
mov     eax, DWORD PTR [ebp-8]
add     DWORD PTR [ebp-4], eax      ; total += i
add     DWORD PTR [ebp-8], 1        ; i++
.L_FOR_TEST:
cmp     DWORD PTR [ebp-8], 10       ; compare i with 10
jle     .L_FOR_BODY
mov     eax, DWORD PTR [ebp-4]
leave
ret

Tabel Stack Memory:

Offset StackNilai InisialPeran Variabel C
[ebp - 4]0int total = 0;
[ebp - 8]1int i = 1;

Penjelasan Langkah Perulangan:

  • Inisialisasi total = 0 dan counter i = 1.
  • Lompat ke .L_FOR_TEST: membandingkan i dengan 10.
  • Jika i <= 10, eksekusi body: total += i, kemudian increment i++.
  • Ketika i = 11, kondisi jle gagal, keluar loop dan return total.

Kode C Final:

C Code
int soal4() {
    int total = 0;
    for (int i = 1; i <= 10; i++) {
        total += i;
    }
    return total;
}
05
Soal 5: Pemanggilan Fungsi Berargumen (x86 cdecl)
Tipe: Function Call & Stack Parameter Passing • Arsitektur: IA-32
x86 Assembly (32-bit)
; --- Fungsi Pembantu: hitung(a, b) ---
hitung:
push    ebp
mov     ebp, esp
mov     edx, DWORD PTR [ebp+8]      ; argumen 1
mov     eax, DWORD PTR [ebp+12]     ; argumen 2
imul    eax, edx
pop     ebp
ret

; --- Fungsi Utama: caller() ---
caller:
push    ebp
mov     ebp, esp
sub     esp, 16
mov     DWORD PTR [ebp-4], 7
mov     DWORD PTR [ebp-8], 6
push    DWORD PTR [ebp-8]           ; push arg2 (6)
push    DWORD PTR [ebp-4]           ; push arg1 (7)
call    hitung
add     esp, 8                      ; caller cleans up stack
mov     DWORD PTR [ebp-12], eax
mov     eax, DWORD PTR [ebp-12]
leave
ret

Analisis Konvensi cdecl:

Parameter didorong ke stack dari kanan ke kiri (push [ebp-8] lalu push [ebp-4]). Di dalam fungsi hitung:

  • [ebp + 8] merujuk pada argumen pertama (nilai 7).
  • [ebp + 12] merujuk pada argumen kedua (nilai 6).
  • imul eax, edx melakukan perkalian: 7 * 6 = 42.
  • Setelah call hitung, perintah add esp, 8 membersihkan 2 argumen (2 * 4 bytes) dari stack.

Kode C Final:

C Code
int hitung(int a, int b) {
    return a * b;
}

int caller() {
    int x = 7;
    int y = 6;
    int res = hitung(x, y);
    return res;
}
06
Soal 6: Pointer & Passing by Reference (x64 64-bit)
Tipe: Memory Pointers (LEA & Registers) • Arsitektur: x86_64
x86_64 Assembly (Linux ABI)
; --- swap(int *p1, int *p2) ---
swap:
push    rbp
mov     rbp, rsp
mov     QWORD PTR [rbp-8], rdi      ; p1 (pointer 8-byte)
mov     QWORD PTR [rbp-16], rsi     ; p2 (pointer 8-byte)
mov     rax, QWORD PTR [rbp-8]
mov     eax, DWORD PTR [rax]        ; temp = *p1
mov     DWORD PTR [rbp-20], eax     ; simpan temp di stack
mov     rax, QWORD PTR [rbp-16]
mov     edx, DWORD PTR [rax]        ; edx = *p2
mov     rax, QWORD PTR [rbp-8]
mov     DWORD PTR [rax], edx        ; *p1 = *p2
mov     rax, QWORD PTR [rbp-16]
mov     edx, DWORD PTR [rbp-20]     ; edx = temp
mov     DWORD PTR [rax], edx        ; *p2 = temp
nop
pop     rbp
ret

; --- main_test() ---
main_test:
push    rbp
mov     rbp, rsp
sub     rsp, 16
mov     DWORD PTR [rbp-4], 100      ; a = 100
mov     DWORD PTR [rbp-8], 200      ; b = 200
lea     rdx, [rbp-8]
lea     rax, [rbp-4]
mov     rsi, rdx                    ; arg 2 = &b
mov     rdi, rax                    ; arg 1 = &a
call    swap
leave
ret

Langkah 1: Identifikasi Passing Parameter via Register RDI & RSI

Pada System V AMD64, rdi menampung alamat &a dan rsi menampung alamat &b yang dihasilkan oleh instruksi lea.

Langkah 2: Tracking Pointer Dereferencing

  • mov rax, [rbp-8] diikuti mov eax, [rax] : membaca nilai integer yang ditunjuk oleh pointer p1 (dereference *p1).
  • DWORD PTR [rbp-20] menyimpan nilai sementara (int temp = *p1).
  • *p1 = *p2; dan *p2 = temp;. Ini adalah algoritma penukaran nilai (swap) menggunakan pointer.

Kode C Final:

C Code
void swap(int *p1, int *p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

void main_test() {
    int a = 100;
    int b = 200;
    swap(&a, &b);
}
07
Soal 7: Array Indexing & Akumulasi Elemen (x64 64-bit)
Tipe: Array 1D & Scale Index Addressing • Arsitektur: x86_64
x86_64 Assembly
sum_array:
push    rbp
mov     rbp, rsp
sub     rsp, 32
; Inisialisasi array 4 elemen int arr[4] = {10, 20, 30, 40};
mov     DWORD PTR [rbp-24], 10      ; arr[0]
mov     DWORD PTR [rbp-20], 20      ; arr[1]
mov     DWORD PTR [rbp-16], 30      ; arr[2]
mov     DWORD PTR [rbp-12], 40      ; arr[3]
mov     DWORD PTR [rbp-4], 0        ; sum = 0
mov     DWORD PTR [rbp-8], 0        ; i = 0
jmp     .L_ARR_COND
.L_ARR_BODY:
mov     eax, DWORD PTR [rbp-8]      ; eax = i
cdqe                                ; convert dword to qword (rax = (long)i)
mov     edx, DWORD PTR [rbp-24+rax*4] ; edx = arr[i] (scale 4 bytes)
add     DWORD PTR [rbp-4], edx      ; sum += arr[i]
add     DWORD PTR [rbp-8], 1        ; i++
.L_ARR_COND:
cmp     DWORD PTR [rbp-8], 3        ; i <= 3
jle     .L_ARR_BODY
mov     eax, DWORD PTR [rbp-4]      ; return sum
leave
ret

Visualisasi Stack Array Memory:

Address OffsetNilaiIndeks Array
[rbp - 24]10 (0x0A)arr[0]
[rbp - 20]20 (0x14)arr[1]
[rbp - 16]30 (0x1E)arr[2]
[rbp - 12]40 (0x28)arr[3]
[rbp - 8]Counter i (0..4)int i
[rbp - 4]Total Sumint sum

Analisis Formula SIB (Scale-Index-Base):

[rbp-24 + rax*4] : Base alamat array berada di rbp-24. Karena elemennya bertipe int (4 bytes), indeks rax dikalikan 4 untuk melompat antar elemen memori.

Kode C Final:

C Code
int sum_array() {
    int arr[4] = {10, 20, 30, 40};
    int sum = 0;
    for (int i = 0; i <= 3; i++) { // atau i < 4
        sum += arr[i];
    }
    return sum;
}
08
Soal 8: Akses Struct Data Members (x64 64-bit)
Tipe: Struct Offset & Alignment • Arsitektur: x86_64
x86_64 Assembly
; Struct Student { int id; int score; char grade; }
get_total:
push    rbp
mov     rbp, rsp
sub     rsp, 16
; inisialisasi struct di stack [rbp-16]
mov     DWORD PTR [rbp-16], 101     ; s.id = 101 (offset 0)
mov     DWORD PTR [rbp-12], 95      ; s.score = 95 (offset 4)
mov     BYTE PTR [rbp-8], 65        ; s.grade = 'A' (ASCII 65, offset 8)
mov     eax, DWORD PTR [rbp-12]     ; ambil score
add     eax, 5                      ; score + 5 bonus
leave
ret

Analisis Layout Memori Struct:

Offset dari [rbp-16]UkuranNilaiField Struct C
+0 byte ([rbp-16])4 byte int101int id;
+4 byte ([rbp-12])4 byte int95int score;
+8 byte ([rbp-8])1 byte char'A' (65)char grade;

Kode C Final:

C Code
struct Student {
    int id;
    int score;
    char grade;
};

int get_total() {
    struct Student s;
    s.id = 101;
    s.score = 95;
    s.grade = 'A';
    return s.score + 5;
}
09
Soal 9: Rekursi Fungsi Fibonacci (x64 64-bit)
Tipe: Recursive Function • Arsitektur: x86_64
x86_64 Assembly
fib:
push    rbp
mov     rbp, rsp
push    rbx                         ; callee-saved register
sub     rsp, 24
mov     DWORD PTR [rbp-20], edi     ; n (parameter pertama)
cmp     DWORD PTR [rbp-20], 1
jg      .L_RECURSE
mov     eax, DWORD PTR [rbp-20]     ; return n jika n <= 1
jmp     .L_END
.L_RECURSE:
mov     eax, DWORD PTR [rbp-20]
sub     eax, 1
mov     edi, eax                    ; arg1 = n - 1
call    fib
mov     ebx, eax                    ; simpan hasil fib(n-1) di ebx
mov     eax, DWORD PTR [rbp-20]
sub     eax, 2
mov     edi, eax                    ; arg1 = n - 2
call    fib
add     eax, ebx                    ; hasil = fib(n-2) + fib(n-1)
.L_END:
add     rsp, 24
pop     rbx
pop     rbp
ret

Langkah Analisis Rekursi:

  • Base Case: cmp [rbp-20], 1; jg .L_RECURSE. Jika n <= 1, langsung lompat ke akhir dan me-return n.
  • Recursive Call 1: Memanggil fib(n - 1), return value disimpan sementara di register ebx.
  • Recursive Call 2: Memanggil fib(n - 2), lalu menjumlahkan eax = fib(n-2) + ebx.

Kode C Final:

C Code
int fib(int n) {
    if (n <= 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}
10
Soal 10: Operasi Bitwise & Masking Enkripsi (x64 64-bit)
Tipe: Bit Manipulation (XOR, SHL, AND) • Arsitektur: x86_64
x86_64 Assembly
crypto_func:
push    rbp
mov     rbp, rsp
mov     DWORD PTR [rbp-4], edi      ; val
mov     DWORD PTR [rbp-8], esi      ; key
mov     eax, DWORD PTR [rbp-4]
xor     eax, DWORD PTR [rbp-8]      ; eax = val ^ key
shl     eax, 2                      ; eax = eax << 2
and     eax, 0x000000FF             ; eax = eax & 0xFF
pop     rbp
ret

Analisis Operasi Bitwise:

  • rdi menampung argumen 1 (val), disimpan di [rbp-4].
  • rsi menampung argumen 2 (key), disimpan di [rbp-8].
  • xor eax, [rbp-8] : Bitwise XOR val ^ key.
  • shl eax, 2 : Bitwise Shift Left sebanyak 2 bit (val ^ key) << 2.
  • and eax, 0xFF : Bitwise AND dengan masker 8-bit (0xFF) ((val ^ key) << 2) & 0xFF.

Kode C Final:

C Code
int crypto_func(int val, int key) {
    int res = (val ^ key) << 2;
    return res & 0xFF;
    // atau ringkas: return ((val ^ key) << 2) & 0xFF;
}