Belajar Assembly - Operasi Aritmetika, Logic & Bitwise
Episode 7 of 23

Belajar Assembly - Operasi Aritmetika, Logic & Bitwise

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.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

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.

Aritmetika Dasar: add, sub, inc, dec

Aritmetika dasar
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.

Overflow: Signed vs Unsigned

Ketika 0xFFFFFFFFFFFFFFFF ditambah 1, hasilnya nol, dan CPU mencatat carry. Apakah ini error? Tergantung interpretasi:

Overflow
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).

Perkalian: mul vs imul

Ini salah satu area yang paling membingungkan pemula. Ada dua instruksi perkalian:

mul (unsigned)

mul rbx mengalikan rax dengan rbx dan hasil 128-bit disimpan di rdx:rax (bagian tinggi di rdx):

mul unsigned
mov rax, 5
mov rbx, 7
mul rbx            ; rdx:rax = rax * rbx = 35
; rax = 35, rdx = 0

imul (signed — dan tiga bentuk)

imul hadir dalam tiga bentuk:

Tiga bentuk imul
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: div vs idiv

Pembagian juga punya dua bentuk, dan keduanya memakai rdx:rax sebagai dividend 128-bit:

div (unsigned)

div unsigned
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)

idiv (signed)

Untuk signed, kalian harus menandatangani-extend rax ke rdx dulu dengan cqo (Convert Quadword to Octword):

idiv signed
mov rax, -100
cqo                ; rdx:rax = sign-extend rax → 64-bit signed
mov rcx, 7
idiv rcx           ; rax = -14, rdx = -2

Warning

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.

Logika: and, or, xor, not

Operasi logika
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:

Manipulasi bit
; 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

Shift dan Rotate

shl, shr, sar

InstruksiNamaPerilaku
shl rax, nShift Left Logicalgeser kiri, bit baru = 0
shr rax, nShift Right Logicalgeser kanan, bit baru = 0
sar rax, nShift Right Arithmeticgeser kanan, pertahankan bit tanda (untuk signed)
Shift
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)

Trik Kompiler: Shift untuk Perkalian/Pembagian Cepat

Karena shift adalah operasi super cepat (1 cycle), compiler mengganti * dan / dengan shift bila pengalinya pangkat dua:

x*8 dan x/16
; x * 8
shl rax, 3
; x / 16 (unsigned)
shr rax, 4
; x / 16 (signed) — perlu pembulatan hati-hati
sar rax, 4

Tip

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.

rol, ror: Rotasi Melingkar

Rotasi memutar bit yang keluar dari satu ujung dan memasukkannya kembali ke ujung lain — dipakai di kriptografi dan hash:

Rotasi
rol rax, 1        ; rotate left — bit tertinggi pindah ke posisi terendah
ror rax, 4        ; rotate right

Penutup

Pada 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.
  • Compiler memilih instruksi berdasarkan harga — dan kalian sekarang mengerti alasannya.

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.

Belajar Assembly - Operasi Aritmetika, Logic & Bitwise | Belajar Assembly