Mengelola data di assembly: peran section .data vs .bss, deklarasi db/dw/dd/dq, array dengan times dan indexing [arr + i*size], string null-terminated dengan loop, implementasi manual strlen dan strcpy, serta layout struct dengan pengaturan padding dan alignment.

Sejauh ini program kalian hanya menangani konstanta dan teks pendek. Episode 11 adalah titik di mana kalian mulai mengelola data nyata: array, string, dan struct — struktur data yang setiap hari kalian pakai di C tanpa berpikir dua kali. Di assembly, semuanya menjadi nyata: kalian melihat byte, alamat, dan layout memori secara langsung.
Mengapa ini penting? Dua alasan. Pertama, sebagian besar codebase assembly dunia nyata adalah library pengolahan data dan format binary. Kedua, memahami layout memori di level byte adalah bekal wajib sebelum masuk ke reverse engineering (16) dan exploit (17) — dua bidang yang seluruhnya tentang memahami bagaimana data diletakkan.
Kedua section ini menyimpan data, tapi dengan karakter berbeda:
| Aspek | section .data | section .bss |
|---|---|---|
| Isi | nilai awal diisi di build time | nilai awal nol (diisi di load time) |
| Ukuran executable | ikut bertambah | tidak (hanya deklarasi ukuran) |
| Cocok untuk | konstanta, string, tabel | buffer, array besar |
| Direktif | db/dw/dd/dq, times | resb/resw/resd/resq, times |
section .data
greeting db "Halo", 0
numbers dd 10, 20, 30, 40 ; array 4 x 4 byte
section .bss
buffer resb 4096 ; 4096 byte nol
counters resq 100 ; 100 qword nolTip
Gunakan .bss untuk buffer besar yang isinya tidak perlu ditentukan di awal — executable kalian tetap kecil karena .bss tidak menyimpan byte di file, hanya janji "sediakan N byte nol saat program dimuat".
Array di assembly hanyalah blok memori berurutan. Elemen ke-i dari array dengan elemen berukuran size berada di alamat base + i*size — persis addressing mode indexed yang kita bahas di episode 5:
section .data
arr dq 100, 200, 300, 400, 500 ; 5 elemen, masing-masing 8 byte
arr_len equ 5
section .text
; rax = arr[i] dengan i di rcx
lea rbx, [arr]
mov rax, [rbx + rcx*8] ; elemen ke-rcx (8 byte per elemen)Contoh lengkap: menjumlahkan semua elemen array.
section .data
arr dq 10, 20, 30, 40, 50
arr_len equ 5
section .text
global _start
_start:
mov rcx, arr_len ; counter = jumlah elemen
xor rax, rax ; sum = 0
lea rbx, [arr] ; rbx = alamat awal array
sum_loop:
add rax, [rbx] ; sum += arr[i]
add rbx, 8 ; maju ke elemen berikutnya
loop sum_loop ; dec rcx; jnz sum_loop
; hasil di rax = 150 — konversi ke desimal (buku) atau syscall exit
mov rax, 60
mov rdi, 150 ; exit code 150 (cukup sebagai bukti)
syscallCek dengan ./sum && echo $? → 150. (Untuk mencetak angka desimal dari register, kita perlu konversi digit — materi yang umum di episode selanjutnya; sebagai pengganti, exit code di sini berfungsi sebagai bukti hitungan.)
Di C, string adalah array char yang diakhiri 0. Konsep yang sama berlaku di assembly:
section .data
s1 db "hello", 0
s2 db 'h', 'e', 'l', 'l', 'o', 0 ; sama persis
s3 db "abc", 0, "def", 0 ; dua string dalam satu blokPanjang string tidak disimpan — ia dihitung dengan berjalan sampai byte nol. Mari implementasikan strlen dan strcpy sendiri:
; input : rdi = alamat string null-terminated
; output: rax = panjang string (tanpa null terminator)
strlen:
xor rax, rax ; panjang = 0
.loop:
cmp byte [rdi + rax], 0
je .done
inc rax
jmp .loop
.done:
ret; input : rdi = alamat tujuan, rsi = alamat sumber
; output: -
strcpy:
xor rax, rax
.copy:
mov cl, [rsi + rax] ; ambil byte sumber
mov [rdi + rax], cl ; tulis ke tujuan
test cl, cl ; byte nol?
jz .done
inc rax
jmp .copy
.done:
retWarning
Perhatikan bahwa strcpy dan strlen tidak tahu batas buffer — mereka berhenti hanya karena byte nol. Jika buffer tujuan terlalu kecil, strcpy menulis melampaui batas: ini persis buffer overflow yang kita eksploitasi di episode 17. Fungsi C modern seperti strncpy/strlcpy hadir justru untuk mencegah pola berbahaya ini.
Perhatikan bahwa implementasi di atas memproses satu byte per iterasi. CPU modern memakai instruksi seperti REPNE SCASB atau bahkan SIMD (episode 12) untuk strlen yang memeriksa 16 byte sekaligus. Sejak era strlen glibc memakai SSE2, itulah contoh nyata mengapa "hitung byte demi byte" jarang ditemukan di library produksi.
Struct di assembly adalah soal menghitung offset. Definisi field menentukan tata letak byte:
; struct Person {
; int age; // offset 0, 4 byte
; long id; // offset 4, 8 byte ← TIDAK ALIGNED!
; char name[8]; // offset 12, 8 byte
; }Versi di atas salah secara alignment: field id (8-byte) berada di offset 4 — tidak kelipatan 8. Kebanyakan arsitektur mengharuskan field diakses pada offset kelipatan ukurannya, atau CPU harus bekerja ekstra (misal di ARM64, akses misaligned bisa crash). Compiler menambahkan padding:
; struct Person {
; int age; // offset 0
; /* 4 byte padding */
; long id; // offset 8
; char name[8]; // offset 16
; }; // total 24 byteAturan alignment paling umum: field tipe N-byte harus berada di offset kelipatan N. Untuk struct bertingkat, offset dihitung relatif terhadap awal struct, dan total ukuran struct biasanya dibulatkan ke kelipatan alignment terbesarnya.
Note
Saat membaca format binary dari disk atau jaringan (misal header PNG, protokol network), kalian sering perlu tahu padding persis — dan di sinilah C bisa mengecoh: sizeof(struct) sering lebih besar dari jumlah field karena padding. Menggunakan __attribute__((packed)) menghapus padding untuk format disk, tetapi mengorbankan kecepatan akses.
Pada episode 11 ini, kalian telah menguasai pengelolaan data di assembly.
Inti yang harus dibawa pulang:
.data untuk nilai awal di build time; .bss untuk buffer nol yang hemat ruang file.i di [base + i*size] (indexed addressing).strlen/strcpy manual menunjukkan mengapa buffer overflow terjadi.Di episode 12 selanjutnya, kita menaikkan level komputasi: SSE/AVX & floating point — dari x87 (FPU stack) ke SSE2 (xmm, addsd/mulsd), SIMD packed operations, register ymm/zmm pada AVX, hingga contoh vektorisasi nyata yang membuat kalian melihat mengapa CPU modern bisa memproses 8 angka sekaligus. Siapkan array kita dari episode ini — kita akan menjumlahkannya dengan cara SIMD!