Menguasai operasi matematika di level register: add/sub, mul/imul yang menghitung 128-bit, div/idiv dengan pembagian signed yang rumit, dan flag overflow CF/OF. Lalu logika & bitwise: and/or/xor/not, shift shl/shr/sar, rotate rol/ror, hingga trik shift sebagai perkalian dan pembagian cepat ala compiler.

Setelah episode 6 mengajarkan cara mengambil keputusan, episode 7 mengajarkan cara menghitung. Aritmetika dan bitwise adalah jantung setiap program nyata — dari loop counter yang menambah 1, sampai operasi hashing, encoding, dan pemeriksaan bit di protocol network.
Ini juga episode di mana kalian mulai melihat mengapa compiler itu pintar: alih-alih mul, compiler memakai shl; alih-alih div, ia memakai pergeseran dan perkalian. Setelah episode ini, kalian akan memahami mengapa — bukan hanya menerima begitu saja.
add rax, rbx ; rax += rbx
add rax, 5 ; rax += 5
sub rax, rbx ; rax -= rbx
inc rax ; rax += 1 (lebih pendek dari add rax,1)
dec rbx ; rbx -= 1
neg rax ; rax = -rax (two's complement)Instruksi ini juga memperbarui flag: hasil nol → ZF=1; carry keluar dari bit tertinggi → CF=1 (untuk unsigned); overflow signed → OF=1.
Ketika 0xFFFFFFFFFFFFFFFF ditambah 1, hasilnya nol, dan CPU mencatat carry. Apakah ini error? Tergantung interpretasi:
mov rax, 0x7FFFFFFFFFFFFFFF ; nilai signed maksimum
add rax, 1 ; rax menjadi 0x8000000000000000
; signed: -9223372036854775808 (OF=1 — salah)
; unsigned: 9223372036854775808 (benar!)CPU tidak peduli kalian menganggap angka itu signed atau unsigned — ia hanya men-set OF dan CF sekaligus. Kalian yang memilih mana yang relevan lewat jump yang dipakai (episode 6).
Ini salah satu area yang paling membingungkan pemula. Ada dua instruksi perkalian:
mul rbx mengalikan rax dengan rbx dan hasil 128-bit disimpan di rdx:rax (bagian tinggi di rdx):
mov rax, 5
mov rbx, 7
mul rbx ; rdx:rax = rax * rbx = 35
; rax = 35, rdx = 0imul hadir dalam tiga bentuk:
imul rax ; satu operan: rax = rax * rax, hasil 128-bit di rdx:rax
imul rax, rbx ; dua operan: rax = rax * rbx (hasil 64-bit)
imul rax, rbx, 3 ; tiga operan: rax = rbx * 3 (konstanta)Bentuk dua dan tiga operan memakai hasil 64-bit, dan men-set CF/OF jika hasil tidak muat di 64 bit — berguna untuk deteksi overflow.
Note
Aturan praktis: hampir selalu gunakan imul dua/dua operan. Untuk nilai signed dan unsigned, bentuk dua operan imul rax, rbx menghasilkan hasil 64-bit yang benar untuk keduanya selama tidak overflow 64-bit — itulah mengapa compiler modern jarang memakai mul.
Pembagian juga punya dua bentuk, dan keduanya memakai rdx:rax sebagai dividend 128-bit:
mov rax, 100 ; dividend (rendah)
mov rdx, 0 ; dividend (tinggi) = 0 → 100
mov rcx, 7 ; divisor
div rcx ; rax = 100 / 7 = 14 (quotient)
; rdx = 100 % 7 = 2 (remainder)Untuk signed, kalian harus menandatangani-extend rax ke rdx dulu dengan cqo (Convert Quadword to Octword):
mov rax, -100
cqo ; rdx:rax = sign-extend rax → 64-bit signed
mov rcx, 7
idiv rcx ; rax = -14, rdx = -2Warning
Kesalahan paling fatal: membagi dengan nol → CPU melempar fault (division error), program crash dengan SIGFPE. Dan pada div/idiv, jika hasil tidak muat di register tujuan, fault yang sama terjadi. Selalu pastikan divisor bukan nol dan hasilnya muat.
and rax, 0xFF ; hanya pertahankan byte rendah
or rax, 0x80 ; set bit ke-7
xor rax, rax ; zeroing register (idiom: lebih cepat dari mov rax,0)
not rax ; komplemen bit
test rax, rbx ; AND tanpa menyimpan hasil (hanya set flag)xor rax, rax adalah idiom yang wajib dihapal — hampir semua compiler memakainya untuk mengosongkan register, karena encodingnya lebih pendek dan eksekusinya lebih cepat daripada mov rax, 0.
Pola operasi bit yang berguna di dunia nyata:
; set bit ke-5 dari rax
or rax, (1 << 5)
; clear bit ke-5
and rax, ~(1 << 5)
; toggle bit ke-5
xor rax, (1 << 5)
; cek bit ke-5 (tanpa mengubah rax)
test rax, (1 << 5)
jnz bit_set| Instruksi | Nama | Perilaku |
|---|---|---|
shl rax, n | Shift Left Logical | geser kiri, bit baru = 0 |
shr rax, n | Shift Right Logical | geser kanan, bit baru = 0 |
sar rax, n | Shift Right Arithmetic | geser kanan, pertahankan bit tanda (untuk signed) |
mov rax, 3
shl rax, 4 ; rax = 48 (3 * 16)
shr rax, 2 ; rax = 12 (48 / 4)
sar rax, 1 ; rax = 6 (untuk signed, tanda dipertahankan)Karena shift adalah operasi super cepat (1 cycle), compiler mengganti * dan / dengan shift bila pengalinya pangkat dua:
; x * 8
shl rax, 3
; x / 16 (unsigned)
shr rax, 4
; x / 16 (signed) — perlu pembulatan hati-hati
sar rax, 4Tip
Hati-hati: sar untuk pembagian signed tidak sama dengan idiv pada angka negatif — sar membulatkan menuju nol-negatif (floor), sedangkan idiv memotong menuju nol. Untuk pembagian signed yang benar dengan pangkat dua, compiler menambahkan konstanta koreksi. Buka Godbolt (episode 20) dan lihat sendiri bagaimana gcc menangani x / 16 untuk int — itu pelajaran berharga.
Rotasi memutar bit yang keluar dari satu ujung dan memasukkannya kembali ke ujung lain — dipakai di kriptografi dan hash:
rol rax, 1 ; rotate left — bit tertinggi pindah ke posisi terendah
ror rax, 4 ; rotate rightPada episode 7 ini, kalian telah menguasai aritmetika dan logika di level register.
Inti yang harus dibawa pulang:
add/sub/inc/dec/neg memperbarui flag; pilih CF (unsigned) atau OF (signed).mul (unsigned, hasil rdx:rax) vs imul (signed, tiga bentuk; pakai bentuk dua operan).div (unsigned) vs idiv (signed, butuh cqo); waspadai pembagian nol.and/or/xor/not/test; hafalkan idiom xor rax, rax untuk zeroing.shl/shr/sar untuk perkalian/pembagian pangkat dua; rol/ror untuk kriptografi.Di episode 8 selanjutnya, kita bedah struktur terpenting dalam pemrograman mesin: stack & subroutine — mekanisme penuh push/pop, manipulasi rsp, stack frame dengan rbp (prologue/epilogue), dan cara variabel lokal hidup di atas stack. Ini juga fondasi untuk memahami calling convention di episode 9 dan buffer overflow di episode 17.