Mempelajari cara mengendalikan alur eksekusi program menggunakan instruksi jump, perbandingan, pengujian bit, dan perulangan pada Assembly 8086.
Capaian Pembelajaran Bab Ini
Setelah mempelajari bab ini, mahasiswa mampu menjelaskan mekanisme instruksi jump bersyarat dan hubungannya dengan register flag; menggunakan instruksi CMP dan TEST untuk membuat keputusan; menulis program dengan struktur percabangan (if-else, nested if) dan perulangan (loop counter, loop bersyarat); serta membedakan penggunaan jump bertanda dan tak bertanda.
Pada bab-bab sebelumnya, program kita selalu dieksekusi secara sekuensial — instruksi demi instruksi dari atas ke bawah. Namun, program yang berguna harus mampu mengambil keputusan (jika kondisi X, lakukan A; selain itu, lakukan B) dan mengulang sekelompok instruksi (ulangi N kali, atau ulangi selama kondisi terpenuhi).
Dalam bahasa tingkat tinggi seperti C, kita menggunakan if-else, switch, for, while, dan do-while. Dalam Assembly 8086, semua konstruksi itu tidak ada secara langsung — kita harus membangunnya dari tiga primitif:
JMP
Lompat tanpa kondisi — implementasi dasar goto
Jxx
Lompat bersyarat — implementasi dasar if
LOOP
Dekrement + lompat — implementasi dasar for
Pemetaan: Bahasa C → Assembly 8086
/* if-else */
if (a > b) {
max = a;
} else {
max = b;
}
Perhatikan: Assembly tidak memiliki blok { } — kita menggunakan label sebagai penanda alur.
9.2 JMP — Jump Tanpa Kondisi
Instruksi JMP adalah bentuk paling sederhana dari kontrol alur. Eksekusi selalu berpindah ke alamat yang ditentukan, tanpa memeriksa kondisi apapun. Ini setara dengan goto dalam bahasa C.
Sintaks JMP
JMPlabel; lompat ke label dalam segmen yang sama (near jump)JMPSHORTlabel; short jump: rentang ±127 byte (lebih hemat memori)JMPWORD PTR [BX] ; indirect jump: lompat ke alamat yang ditunjuk BX
Penggunaan Utama JMP
▶Keluar dari blok if-else: Setelah mengeksekusi blok if, JMP digunakan untuk melewati blok else.
▶Keluar dari loop: Break dari loop ketika kondisi tertentu terpenuhi sebelum counter habis.
▶Implementasi switch-case: Dengan tabel alamat (jump table) dan indirect jump.
▶Infinite loop:JMP $ atau label: JMP label untuk menghentikan program.
Contoh: If-Else sederhana
; Menentukan nilai maksimum dari AX dan BX; Hasil disimpan di variabel 'maks'CMPAX, BX; bandingkan AX dengan BXJNGbx_lebih_besar; jika AX ≤ BX (signed), lompatMOVmaks, AX; blok IF: AX lebih besarJMPselesai; ← penting! lewati blok elsebx_lebih_besar:MOVmaks, BX; blok ELSE: BX lebih besarselesai:; eksekusi dilanjutkan di sini
Kode 9.1: Pola dasar if-else menggunakan CMP, JNG (jump bersyarat), dan JMP (untuk melewati blok else).
⚠ Kesalahan Umum: Lupa menulis JMP selesai setelah blok if. Tanpa JMP tersebut, eksekusi akan "jatuh" ke dalam blok else dan menjalankannya juga — menghasilkan logika yang salah. Ini adalah bug paling klasik dalam pemrograman Assembly.
9.3 Register Flag Relevan
Semua instruksi jump bersyarat bekerja dengan memeriksa register flag di dalam Flags Register. Pada bab ini, flag yang paling relevan adalah:
Flag
Bit
Nama Lengkap
Diset (1) Ketika...
Digunakan Untuk
ZF
Bit 6
Zero Flag
Hasil operasi = 0
JZ/JNZ, JE/JNE, LOOPE/LOOPNE
CF
Bit 0
Carry Flag
Ada carry/borrow pada bit tertinggi (unsigned)
JC/JNC, JB/JAE/JBE/JA
SF
Bit 7
Sign Flag
Bit tertinggi hasil = 1 (hasil negatif dalam signed)
JS/JNS, JG/JGE/JL/JLE (kombinasi dengan OF)
OF
Bit 11
Overflow Flag
Overflow terjadi pada operasi signed
JO/JNO, JG/JGE/JL/JLE (kombinasi dengan SF)
PF
Bit 2
Parity Flag
Jumlah bit 1 di byte rendah hasil adalah genap
JP/JNP (jarang digunakan)
Flags Register (16-bit) — bit yang relevan dihighlight
OF
15
—
14
—
13
—
12
OF
11
DF
10
IF
9
TF
8
SF
7
ZF
6
—
5
AF
4
—
3
PF
2
—
1
CF
0
Gambar 9.1: Flags Register 8086. Bit yang dihighlight adalah flag yang digunakan oleh instruksi kontrol alur program.
Alur Kerja: Operasi → Flag → Keputusan
CMP / TEST / SUB / ADD / AND / ...→Update ZF, CF, SF, OF→JZ / JA / JG / ...→Lompat / Lanjut
Pola fundamental: lakukan operasi yang mempengaruhi flag, lalu gunakan jump bersyarat untuk mengambil keputusan.
9.4 CMP — Perbandingan
CMP adalah instruksi paling penting dalam pengambilan keputusan. Secara internal, CMP melakukan pengurangan (dest − src) tetapi tidak menyimpan hasilnya — hanya register flag yang diperbarui.
Berikut adalah tabel flag yang dihasilkan CMP untuk berbagai hubungan antara dest dan src:
Kondisi (dest vs src)
ZF
CF
SF
OF
Jump Unsigned
Jump Signed
dest = src
1
0
0
0
JE / JZ
JE / JZ
dest > src (unsigned)
0
0
—
—
JA / JNBE
—
dest < src (unsigned)
0
1
—
—
JB / JNAE
—
dest > src (signed)
0
—
—
—
—
JG / JNLE
dest < src (signed)
0
—
—
—
—
JL / JNGE
Tabel 9.1: Hubungan antara kondisi perbandingan, nilai flag, dan instruksi jump yang sesuai. Tanda "—" berarti nilai flag tersebut tidak relevan untuk kondisi tersebut.
Cara Mudah Mengingat:CMP dest, src membaca "bandingkan dest dengan src". Jump yang mengikuti menjawab pertanyaan tentang dest: "apakah dest lebih besar?", "apakah dest sama dengan?", dsb. Jadi posisi operand penting — CMP AX, BX berbeda maknanya dengan CMP BX, AX.
9.5 TEST — Pengujian Bit
TEST melakukan operasi AND secara internal (dest AND src) tanpa menyimpan hasilnya. Hanya flag yang diperbarui. TEST sangat berguna untuk:
•Mengecek apakah register = 0:TEST AX, AX → jika AX=0 maka ZF=1
•Mengecek bit tertentu:TEST AL, 01h → cek bit 0 (bilangan ganjil/genap)
•Mengecek apakah bit tertentu set:TEST AX, 80h → cek bit tertinggi
Contoh: TEST untuk cek ganjil/genap
; Cek apakah AL bernilai genapTESTAL, 01h; AND internal: AL AND 00000001bJZgenap; jika bit 0 = 0 (ZF=1), bilangan genap; ... kode untuk ganjil ...JMPselesaigenap:; ... kode untuk genap ...selesai:; Cek apakah AX bernilai nolTESTAX, AX; AX AND AX = AX, tapi tidak disimpanJNZtidak_nol; jika AX ≠ 0 (ZF=0), lompat; ... kode untuk AX = 0 ...
Kode 9.2: Penggunaan TEST untuk mengecek bit spesifik dan mengecek nol.
TEST vs CMP vs AND
Aspek
TEST
CMP
AND
Operasi Internal
dest AND src
dest − src
dest AND src
Menyimpan Hasil?
Tidak
Tidak
Ya
Flag Terpengaruh
ZF, SF, PF (CF=0, OF=0)
ZF, CF, SF, OF, PF, AF
ZF, SF, PF (CF=0, OF=0)
Kegunaan Utama
Cek bit / cek nol
Perbandingan nilai
Masking bit
9.6 Jump Bersyarat: Berdasarkan Single Flag
Kelompok pertama jump bersyarat memeriksa satu flag saja. Ini adalah instruksi paling dasar dan sering digunakan setelah TEST atau operasi bit manipulation.
Instruksi
Alias
Kondisi Lompat
Penjelasan
JZ
JE
ZF = 1
Jump if Zero / Equal — hasil operasi = 0 atau operand sama
JNZ
JNE
ZF = 0
Jump if Not Zero / Not Equal — hasil ≠ 0 atau operand berbeda
JC
JB, JNAE
CF = 1
Jump if Carry — ada carry/borrow (unsigned: dest < src)
JNC
JAE, JNB
CF = 0
Jump if No Carry — tidak ada carry (unsigned: dest ≥ src)
JS
—
SF = 1
Jump if Sign — hasil operasi negatif (bit tertinggi = 1)
JNS
—
SF = 0
Jump if Not Sign — hasil operasi non-negatif
JO
—
OF = 1
Jump if Overflow — terjadi overflow pada operasi signed
JNO
—
OF = 0
Jump if No Overflow — tidak ada overflow
JP
JPE
PF = 1
Jump if Parity Even — parity genap (jarang dipakai)
JNP
JPO
PF = 0
Jump if Parity Odd — parity ganjil (jarang dipakai)
Contoh: Pencarian karakter dalam string
; Mencari karakter '$' dalam string, pointer di SIcari_dollar:MOVAL, [SI] ; baca satu karakterCMPAL, '$'; apakah karakter '$'?JEketemu; ya! ZF=1, lompat ke 'ketemu'INCSI; tidak, maju ke karakter berikutnyaJMPcari_dollar; ulangi pencarianketemu:; SI menunjuk ke karakter '$' yang ditemukan
Kode 9.3: Pola pencarian linear menggunakan CMP + JE + JMP.
9.7 Jump Bersyarat: Berdasarkan Perbandingan Bertanda (Signed)
Instruksi ini digunakan setelah CMP ketika data diinterpretasikan sebagai bilangan bertanda (signed). Mereka memeriksa kombinasi SF dan OF, bukan CF.
Instruksi
Alias
Kondisi
Makna (dest vs src)
JG
JNLE
ZF=0 AND SF=OF
dest lebih besar dari src (signed)
JGE
JNL
SF = OF
dest lebih besar atau sama dengan src (signed)
JL
JNGE
SF ≠ OF
dest lebih kecil dari src (signed)
JLE
JNG
ZF=1 OR SF≠OF
dest lebih kecil atau sama dengan src (signed)
Cara Mengingat Alias: JG = JNLE (Greater = Not Less nor Equal). JGE = JNL (Greater or Equal = Not Less). JL = JNGE (Less = Not Greater nor Equal). JLE = JNG (Less or Equal = Not Greater). Setiap instruksi memiliki kebalikan logisnya.
Contoh: Klasifikasi suhu (signed)
; Klasifikasi suhu di AL (bertanda):; < 0 → "Dingin"; 0-25 → "Nyaman"; > 25 → "Panas"CMPAL, 0; bandingkan dengan 0JLdinginCMPAL, 25; bandingkan dengan 25JGpanas; signed: AL > 25?; jika sampai sini: 0 ≤ AL ≤ 25LEADX, msg_nyaman
JMPtampilkandingin:LEADX, msg_dingin
JMPtampilkanpanas:LEADX, msg_panas
tampilkan:MOVAH, 09hINT21h
Kode 9.4: Struktur if-else-if menggunakan CMP + JL + JG (signed comparison).
9.8 Jump Bersyarat: Berdasarkan Perbandingan Tak Bertanda (Unsigned)
Instruksi ini digunakan setelah CMP ketika data diinterpretasikan sebagai bilangan tak bertanda (unsigned) — yaitu nilai selalu positif. Mereka memeriksa flag CF.
Instruksi
Alias
Kondisi
Makna (dest vs src)
JA
JNBE
CF=0 AND ZF=0
dest di atas src (unsigned: dest > src)
JAE
JNC, JNB
CF = 0
dest di atas atau sama dengan src (unsigned: dest ≥ src)
JB
JNAE, JC
CF = 1
dest di bawah src (unsigned: dest < src)
JBE
JNA
CF=1 OR ZF=1
dest di bawah atau sama dengan src (unsigned: dest ≤ src)
⚠ Peringatan: Jangan Campur Signed & Unsigned!
Menggunakan jump yang salah akan menghasilkan bug yang sulit dilacak. Contoh:
MOVAL, 0FFh; AL = 255 (unsigned) atau -1 (signed)CMPAL, 01h; bandingkan dengan 1; Jika pakai JA (unsigned): 255 > 1 → LOMPAT ✓; Jika pakai JG (signed): -1 > 1 → TIDAK lompat ✗MOVAL, 80h; AL = 128 (unsigned) atau -128 (signed)CMPAL, 7Fh; bandingkan dengan 127; Jika pakai JA (unsigned): 128 > 127 → LOMPAT ✓; Jika pakai JG (signed): -128 > 127 → TIDAK lompat ✗
9.9 Instruksi Perulangan (LOOP)
8086 menyediakan instruksi khusus untuk implementasi loop yang otomatis mendekrement register CX. Ada empat varian:
Instruksi
Operasi Internal
Kondisi Lompat
Ungkapan C
LOOP
CX ← CX − 1
CX ≠ 0
while (--cx != 0)
LOOPE
CX ← CX − 1
CX ≠ 0 AND ZF = 1
while (--cx != 0 && zero_flag)
LOOPNE
CX ← CX − 1
CX ≠ 0 AND ZF = 0
while (--cx != 0 && !zero_flag)
JCXZ
Tidak mengubah CX
CX = 0
if (cx == 0) goto label
Catatan Nama: LOOPE juga dikenal sebagai LOOPZ (Loop while Zero). LOOPNE juga dikenal sebagai LOOPNZ (Loop while Not Zero). Keduanya adalah instruksi yang sama, hanya nama alias yang berbeda.
Contoh: LOOP dasar — jumlah 1 sampai N
; Menghitung jumlah 1 + 2 + 3 + ... + N; N disimpan di variabel 'n', hasil di 'jumlah'MOVCX, n; CX = N (counter loop)XORAX, AX; AX = 0 (akumulator jumlah)MOVBX, 1; BX = 1 (bilangan pertama)jumlah_loop:ADDAX, BX; jumlah += BXINCBX; BX++ (bilangan berikutnya)LOOPjumlah_loop; CX--; jika CX ≠ 0, ulangiMOVjumlah, AX; simpan hasil
Kode 9.5: Loop counter sederhana menggunakan LOOP.
Contoh: LOOPE — cari karakter yang berbeda
; Mencari karakter PERTAMA yang BUKAN 'A' dalam string; Panjang string di CX, pointer di SIJCXZsemua_A; jika CX=0, string kosong, lewatcari_bukan_A:CMPBYTE PTR [SI], 'A'; apakah karakter ini 'A'?LOOPEcari_bukan_A; CX--; lompat jika CX≠0 DAN ZF=1 (masih 'A'); Di sini: SI menunjuk ke karakter bukan 'A', ATAU CX sudah 0JCXZsemua_A; jika CX=0, semua karakter adalah 'A'; Ketemu karakter bukan 'A' di [SI]JMPselesaisemua_A:; Semua karakter adalah 'A'selesai:
Kode 9.6: LOOPE digunakan untuk mencari elemen pertama yang tidak memenuhi kondisi. Perhatikan penggunaan JCXZ untuk menangani kasus edge (string kosong / semua cocok).
9.10 Contoh Program: Menentukan Bilangan Terbesar
Program berikut mencari nilai terbesar dari sebuah array bilangan 16-bit. Ini adalah contoh klasik yang menggabungkan loop, perbandingan, dan jump bersyarat.
Assembly 8086
.model small
.stack100h.data
array dw34, 78, 12, 95, 63, 41, 89, 27
n dw8; jumlah elemen
maks dw?; penyimpanan hasil
msg db'Bilangan terbesar: $'.codemulai:MOVAX, @dataMOVDS, AXMOVCX, n; CX = jumlah elemenDECCX; CX = n-1 (perlu n-1 perbandingan)MOVSI, 0; SI = index array (byte offset)MOVBX, array[SI] ; BX = elemen pertama (asumsi terbesar)bandingkan:ADDSI, 2; maju ke elemen berikutnya (word = 2 byte)MOVAX, array[SI] ; AX = elemen saat iniCMPAX, BX; bandingkan dengan current maxJNGlanjut; jika AX ≤ BX (signed), bukan yang lebih besarMOVBX, AX; AX > BX: update maks barulanjut:LOOPbandingkan; CX--; ulangi jika CX ≠ 0MOVmaks, BX; simpan hasil ke memori; Tampilkan pesan (tanpa menampilkan angkanya untuk kesederhanaan)MOVAH, 09hLEADX, msg
INT21hMOVAH, 4ChINT21hend mulai
Kode 9.7: Pencarian nilai maksimum array — menggabungkan LOOP, CMP, JNG, dan JMP implisit.
Trace Eksekusi (Langkah demi Langkah)
Iterasi
CX
SI
array[SI]
BX (maks)
CMP
Aksi
Awal
7
0
34
34
—
Inisialisasi
1
7
2
78
34
78 > 34
Update BX = 78
2
6
4
12
78
12 ≤ 78
Tidak update
3
5
6
95
78
95 > 78
Update BX = 95
4
4
8
63
95
63 ≤ 95
Tidak update
5
3
10
41
95
41 ≤ 95
Tidak update
6
2
12
89
95
89 ≤ 95
Tidak update
7
1
14
27
95
27 ≤ 95
Tidak update
Selesai
0
14
—
95
—
Maks = 95
9.11 Contoh Program: Klasifikasi Nilai (If-Else If-Else)
Program berikut mengklasifikasikan nilai ujian menjadi huruf mutu (A, B, C, D, E). Ini mendemonstrasikan struktur if-else if-else bertingkat.
Assembly 8086
; Klasifikasi nilai ujian (0-100) menjadi huruf mutu; Nilai di variabel 'nilai', huruf mutu disimpan di 'grade'; A: ≥80, B: ≥70, C: ≥55, D: ≥40, E: <40MOVAL, nilai; ambil nilaiCMPAL, 80; nilai ≥ 80?JAEgrade_ACMPAL, 70; nilai ≥ 70?JAEgrade_BCMPAL, 55; nilai ≥ 55?JAEgrade_CCMPAL, 40; nilai ≥ 40?JAEgrade_D; Jika sampai sini: nilai < 40MOVgrade, 'E'JMPselesaigrade_A:MOVgrade, 'A'JMPselesaigrade_B:MOVgrade, 'B'JMPselesaigrade_C:MOVgrade, 'C'JMPselesaigrade_D:MOVgrade, 'D'selesai:
Kode 9.8: Pola if-else if-else menggunakan CMP + JAE + JMP. Perhatikan setiap blok diakhiri JMP selesai kecuali blok terakhir.
Mulai: nilai di AL
AL ≥ 80?
Ya ↓
grade = 'A'
Tidak →
AL ≥ 70?
Ya ↓
'B'
Tidak →
≥55?
... dst
↓ (semua cabang) ↓
Selesai
Gambar 9.2: Diagram alur (flowchart) klasifikasi nilai. Setiap cabang "Ya" langsung menuju "Selesai" melalui JMP.
9.12 Contoh Program: Menghitung Jumlah Bilangan Genap
Program ini mendemonstrasikan kombinasi TEST (untuk cek bit) dengan LOOP (untuk iterasi) — dua teknik kontrol alur yang bekerja bersama.
Assembly 8086
.model small
.stack100h.data
bilangan dw15, 22, 33, 44, 55, 66, 77, 88, 99, 100
n dw10
jml_genap dw0.codemulai:MOVAX, @dataMOVDS, AXMOVCX, n; counter = 10MOVSI, 0; index arrayMOVBX, 0; BX = penghitung genapcek_genap:MOVAX, bilangan[SI] ; ambil bilanganTESTAX, 0001h; cek bit 0JNZganjil; bit 0 = 1 → ganjil, lewatiINCBX; bit 0 = 0 → genap, tambah counterganjil:ADDSI, 2; maju ke word berikutnyaLOOPcek_genap; ulangiMOVjml_genap, BX; simpan hasil: 5MOVAH, 4ChINT21hend mulai
Kode 9.9: Penghitungan bilangan genap menggunakan TEST untuk cek paritas dan LOOP untuk iterasi.
Mengapa TEST Bukan CMP untuk Cek Genap?
Kita bisa menulis CMP AX, 2 lalu cek sisa pembagian — tapi itu membutuhkan instruksi DIV yang kompleks. Cara yang jauh lebih efisien adalah TEST AX, 01h: bilangan genap selalu memiliki bit 0 = 0. TEST hanya membutuhkan 3 byte dan 2 clock cycle, sedangkan DIV membutuhkan lebih banyak. Ini adalah teknik bitwise trick yang umum di Assembly.
9.13 Tabel Ringkasan Semua Instruksi Jump
Tabel berikut merangkum seluruh instruksi jump pada 8086 sebagai referensi cepat. Instruksi dengan warna sama berfungsi identik (alias).
Kondisi
Signed
Unsigned
Single Flag
Flag yang Diperiksa
Sama dengan (=)
JE / JZ
JE / JZ
JZ
ZF = 1
Tidak sama dengan (≠)
JNE / JNZ
JNE / JNZ
JNZ
ZF = 0
Lebih besar (>)
JG / JNLE
JA / JNBE
—
S: ZF=0,SF=OF U: CF=0,ZF=0
Lebih besar atau sama (≥)
JGE / JNL
JAE / JNB / JNC
—
S: SF=OF U: CF=0
Lebih kecil (<)
JL / JNGE
JB / JNAE / JC
—
S: SF≠OF U: CF=1
Lebih kecil atau sama (≤)
JLE / JNG
JBE / JNA
—
S: ZF=1 or SF≠OF U: CF=1 or ZF=1
Carry terjadi
—
—
JC
CF = 1
Negatif
—
—
JS
SF = 1
Overflow
—
—
JO
OF = 1
Tanpa kondisi
JMP
—
Selalu lompat
CX = 0
JCXZ
—
CX = 0 (bukan flag)
Tips Mnemonic: Signed
Greater = lebih besar (signed)
Less = lebih kecil (signed)
Equal = sama dengan
N = Not (kebalikan)
Tips Mnemonic: Unsigned
Above = di atas / lebih besar (unsigned)
Below = di bawah / lebih kecil (unsigned)
Equal = sama dengan
N = Not (kebalikan)
9.14 Soal Latihan
Kerjakan soal-soal berikut untuk menguji pemahaman Anda. Klik "Lihat jawaban" setelah mencoba menjawab sendiri.
Soal 1. Apa perbedaan mendasar antara instruksi JMP dan instruksi jump bersyarat (misalnya JZ, JNZ)?
▶ Lihat jawaban
JMP adalah jump tanpa kondisi — eksekusi selalu berpindah ke label tujuan, tidak memeriksa flag apapun. Sedangkan jump bersyarat (JZ, JNZ, JC, JAE, JG, dll.) hanya akan melompat jika kondisi flag tertentu terpenuhi. Jika kondisi tidak terpenuhi, eksekusi lanjut ke instruksi berikutnya secara sekuensial.
Soal 2. Mengapa instruksi CMP disebut "perbandingan tanpa mengubah data"? Jelaskan mekanisme internalnya.
▶ Lihat jawaban
CMP melakukan operasi pengurangan internal (operand1 − operand2) tetapi hasilnya tidak disimpan ke mana pun — kedua operand tetap utuh. Yang berubah hanyalah register flag (ZF, CF, SF, OF) berdasarkan hasil pengurangan tersebut. Dengan begitu, program bisa memeriksa hubungan antara dua nilai tanpa merusak datanya.
Soal 3. Jelaskan perbedaan antara jump bersyarat bertanda (signed) dan tak bertanda (unsigned). Kapan menggunakan masing-masing?
▶ Lihat jawaban
Jump bertanda (JG, JGE, JL, JLE) memeriksa flag SF dan OF untuk menentukan apakah nilai bertanda lebih besar/kecil. Digunakan saat data diinterpretasikan sebagai bilangan bulat bertanda (misal: suhu, saldo). Jump tak bertanda (JA, JAE, JB, JBE) memeriksa flag CF untuk menentukan urutan. Digunakan saat data diinterpretasikan sebagai bilangan positif murni (misal: alamat memori, jumlah item, panjang string). Menggunakan jump yang salah akan menghasilkan logika yang keliru.
Soal 4. Apa yang terjadi jika Anda menggunakan JA untuk membandingkan dua bilangan negatif, misalnya −5 dan −10? Mengapa hasilnya salah?
▶ Lihat jawaban
Dalam representasi two's complement 16-bit, −5 = FFFBh dan −10 = FFF6h. Jika diperlakukan sebagai bilangan tak bertanda, FFFBh (65531) > FFF6h (65526), sehingga JA akan melompat — ini benar secara unsigned. Namun secara logika bertanda, −5 > −10 juga benar. Masalahnya muncul jika nilai berbeda tanda, misalnya −1 (FFFFh = 65535 unsigned) vs +1 (0001h). Secara signed −1 < +1, tapi secara unsigned FFFFh > 0001h sehingga JA salah digunakan di sini.
Soal 5. Tulis program Assembly 8086 yang menghitung jumlah bilangan genap dari 10 bilangan yang tersimpan di memori. Jelaskan alur logikanya.
▶ Lihat jawaban
Logika: Inisialisasi counter = 10, jumlah_genap = 0, pointer ke data. Untuk setiap bilangan: AND dengan 1. Jika hasilnya 0 (ZF=1), bilangan genap → tambah jumlah_genap. Decrement counter, ulangi sampai counter = 0.
Kode: MOV CX, 10 MOV SI, 0 MOV BX, 0 loop_genap: MOV AX, data[SI] TEST AX, 0001h JNZ lanjut INC BX lanjut: ADD SI, 2 LOOP loop_genap ; BX sekarang berisi jumlah bilangan genap
Soal 6. Bandingkan LOOP dengan DEC CX + JNZ. Apa keuntungan menggunakan LOOP?
▶ Lihat jawaban
Secara fungsional, LOOP label setara dengan DEC CX diikuti JNZ label. Keuntungan LOOP: (1) lebih ringkas — satu instruksi menggantikan dua, (2) lebih efisien — pada 8086 LOOP membutuhkan fewer bytes di memori (2 byte vs 3 byte total untuk DEC+JNZ), dan (3) kode lebih mudah dibaca. Kerugiannya: LOOP selalu menggunakan CX, tidak bisa pakai register lain.
9.15 Kuis Bab 9
Uji pemahaman Anda. Pilih satu jawaban yang paling tepat. Setelah memilih, jawaban benar akan ditandai dan penjelasan muncul.
1. Instruksi mana yang TIDAK mengubah nilai flag?
JMP adalah jump tanpa kondisi dan tidak memeriksa maupun mengubah flag. CMP, TEST, dan SUB semuanya mempengaruhi flag (ZF, SF, CF, OF, PF, AF).
2. Setelah instruksi CMP AL, 5 dieksekusi dan AL berisi 5, flag apa yang pasti bernilai 1?
CMP melakukan AL − 5. Karena AL = 5, hasilnya 0, sehingga ZF = 1 (Zero Flag set karena hasil nol). CF = 0 (tidak ada borrow), SF = 0 (hasil bukan negatif), OF = 0 (tidak ada overflow).
3. Instruksi jump mana yang tepat untuk memeriksa "jika AL ≥ BL" untuk bilangan bertanda (signed)?
JGE (Jump if Greater or Equal, signed) melompat jika SF = OF. Ini memeriksa apakah operand pertama ≥ operand kedua untuk bilangan bertanda. JAE/JA adalah versi unsigned-nya.
LOOP mendekrement CX lalu memeriksa: jika CX ≠ 0, lompat ke label. CX berkurang: 3→2 (lompat), 2→1 (lompat), 1→0 (tidak lompat, lanjut). Jadi eksekusi badan loop tepat 3 kali.
5. Apa fungsi instruksi TEST AX, AX?
TEST melakukan operasi AND internal (AX AND AX) tanpa menyimpan hasilnya. AX tetap tidak berubah. Jika AX = 0, hasil AND = 0 sehingga ZF = 1. Ini adalah cara idiomatis untuk mengecek apakah register bernilai nol.
6. Setelah CMP AX, BX, dengan AX = 0002h dan BX = 0005h, instruksi jump mana yang TIDAK akan melompat?
AX(2) < BX(5) secara unsigned. JB/JNAE melompat karena CF=1 (ada borrow). JBE melompat karena CF=1 ATAU ZF=0 (benar keduanya). JA hanya melompat jika CF=0 AND ZF=0 — tapi di sini CF=1, jadi JA TIDAK melompat.
7. JCXZ label akan melompat ketika...
JCXZ (Jump if CX is Zero) memeriksa register CX secara langsung, BUKAN flag. Jika CX = 0, instruksi ini melompat ke label. Berguna untuk menangani kasus di mana counter loop sudah nol sebelum loop dimulai.
8. LOOPE label sama dengan...
LOOPE (Loop while Equal/Zero) mendekrement CX, lalu melompat HANYA jika CX ≠ 0 DAN ZF = 1. Jadi kedua kondisi harus terpenuhi. Digunakan untuk mencari elemen pertama yang TIDAK sama dengan nilai tertentu.