Minggu 9 Pemrograman

Bab 9: Kontrol Alur Program

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.

9.1 Mengapa Kontrol Alur Diperlukan

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;
}
; if-else CMP AX, BX
JNG else_label
MOV max, AX
JMP done
else_label:
MOV max, BX
done:
/* for loop */ for (i = 0; i < 10; i++) {
  sum += arr[i];
}
; for loop MOV CX, 10
MOV SI, 0
XOR AX, AX
loop_for:
ADD AX, arr[SI]
ADD SI, 2
LOOP loop_for

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
JMP  label      ; lompat ke label dalam segmen yang sama (near jump)
JMP  SHORT label  ; short jump: rentang ±127 byte (lebih hemat memori)
JMP  WORD 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'

    CMP  AX, BX          ; bandingkan AX dengan BX
    JNG  bx_lebih_besar  ; jika AX ≤ BX (signed), lompat

    MOV  maks, AX        ; blok IF: AX lebih besar
    JMP  selesai          ; ← penting! lewati blok else

bx_lebih_besar:
    MOV  maks, BX        ; blok ELSE: BX lebih besar

selesai:
    ; 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:

FlagBitNama LengkapDiset (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.

Sintaks CMP
CMP  register, register    ; CMP AX, BX
CMP  register, immediate  ; CMP AL, 10
CMP  register, memory      ; CMP AX, [SI]
CMP  memory, immediate    ; CMP byte ptr [BX], 0
CMP  memory, register      ; CMP [DI], CX

Berikut adalah tabel flag yang dihasilkan CMP untuk berbagai hubungan antara dest dan src:

Kondisi (dest vs src)ZFCFSFOFJump UnsignedJump 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 pentingCMP 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 genap
    TEST AL, 01h          ; AND internal: AL AND 00000001b
    JZ   genap            ; jika bit 0 = 0 (ZF=1), bilangan genap
    ; ... kode untuk ganjil ...
    JMP  selesai
genap:
    ; ... kode untuk genap ...
selesai:

; Cek apakah AX bernilai nol
    TEST AX, AX           ; AX AND AX = AX, tapi tidak disimpan
    JNZ  tidak_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

AspekTESTCMPAND
Operasi Internaldest AND srcdest − srcdest AND src
Menyimpan Hasil?TidakTidakYa
Flag TerpengaruhZF, SF, PF (CF=0, OF=0)ZF, CF, SF, OF, PF, AFZF, SF, PF (CF=0, OF=0)
Kegunaan UtamaCek bit / cek nolPerbandingan nilaiMasking 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.

InstruksiAliasKondisi LompatPenjelasan
JZJEZF = 1Jump if Zero / Equal — hasil operasi = 0 atau operand sama
JNZJNEZF = 0Jump if Not Zero / Not Equal — hasil ≠ 0 atau operand berbeda
JCJB, JNAECF = 1Jump if Carry — ada carry/borrow (unsigned: dest < src)
JNCJAE, JNBCF = 0Jump if No Carry — tidak ada carry (unsigned: dest ≥ src)
JSSF = 1Jump if Sign — hasil operasi negatif (bit tertinggi = 1)
JNSSF = 0Jump if Not Sign — hasil operasi non-negatif
JOOF = 1Jump if Overflow — terjadi overflow pada operasi signed
JNOOF = 0Jump if No Overflow — tidak ada overflow
JPJPEPF = 1Jump if Parity Even — parity genap (jarang dipakai)
JNPJPOPF = 0Jump if Parity Odd — parity ganjil (jarang dipakai)
Contoh: Pencarian karakter dalam string
; Mencari karakter '$' dalam string, pointer di SI
cari_dollar:
    MOV  AL, [SI]        ; baca satu karakter
    CMP  AL, '$'          ; apakah karakter '$'?
    JE   ketemu            ; ya! ZF=1, lompat ke 'ketemu'
    INC  SI                ; tidak, maju ke karakter berikutnya
    JMP  cari_dollar       ; ulangi pencarian

ketemu:
    ; 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.

InstruksiAliasKondisiMakna (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"

    CMP  AL, 0             ; bandingkan dengan 0
    JL   dingin           
    CMP  AL, 25            ; bandingkan dengan 25
    JG   panas             ; signed: AL > 25?
    ; jika sampai sini: 0 ≤ AL ≤ 25
    LEA  DX, msg_nyaman
    JMP  tampilkan

dingin:
    LEA  DX, msg_dingin
    JMP  tampilkan

panas:
    LEA  DX, msg_panas

tampilkan:
    MOV  AH, 09h
    INT  21h

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.

InstruksiAliasKondisiMakna (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:

MOV AL, 0FFh ; AL = 255 (unsigned) atau -1 (signed) CMP AL, 01h ; bandingkan dengan 1 ; Jika pakai JA (unsigned): 255 > 1 → LOMPAT ✓ ; Jika pakai JG (signed): -1 > 1 → TIDAK lompat ✗ MOV AL, 80h ; AL = 128 (unsigned) atau -128 (signed) CMP AL, 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:

InstruksiOperasi InternalKondisi LompatUngkapan 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'

    MOV  CX, n            ; CX = N (counter loop)
    XOR  AX, AX           ; AX = 0 (akumulator jumlah)
    MOV  BX, 1             ; BX = 1 (bilangan pertama)

jumlah_loop:
    ADD  AX, BX           ; jumlah += BX
    INC  BX                ; BX++ (bilangan berikutnya)
    LOOP jumlah_loop       ; CX--; jika CX ≠ 0, ulangi

    MOV  jumlah, 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 SI

    JCXZ semua_A           ; jika CX=0, string kosong, lewat

cari_bukan_A:
    CMP  BYTE PTR [SI], 'A'  ; apakah karakter ini 'A'?
    LOOPE cari_bukan_A      ; CX--; lompat jika CX≠0 DAN ZF=1 (masih 'A')

    ; Di sini: SI menunjuk ke karakter bukan 'A', ATAU CX sudah 0
    JCXZ semua_A           ; jika CX=0, semua karakter adalah 'A'

    ; Ketemu karakter bukan 'A' di [SI]
    JMP  selesai

semua_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
.stack 100h

.data
    array  dw 34, 78, 12, 95, 63, 41, 89, 27
    n      dw 8                     ; jumlah elemen
    maks   dw ?                    ; penyimpanan hasil
    msg    db 'Bilangan terbesar: $'

.code
mulai:
    MOV  AX, @data
    MOV  DS, AX

    MOV  CX, n             ; CX = jumlah elemen
    DEC  CX                ; CX = n-1 (perlu n-1 perbandingan)
    MOV  SI, 0             ; SI = index array (byte offset)
    MOV  BX, array[SI]      ; BX = elemen pertama (asumsi terbesar)

bandingkan:
    ADD  SI, 2             ; maju ke elemen berikutnya (word = 2 byte)
    MOV  AX, array[SI]      ; AX = elemen saat ini
    CMP  AX, BX           ; bandingkan dengan current max
    JNG  lanjut            ; jika AX ≤ BX (signed), bukan yang lebih besar
    MOV  BX, AX           ; AX > BX: update maks baru

lanjut:
    LOOP bandingkan        ; CX--; ulangi jika CX ≠ 0

    MOV  maks, BX           ; simpan hasil ke memori

    ; Tampilkan pesan (tanpa menampilkan angkanya untuk kesederhanaan)
    MOV  AH, 09h
    LEA  DX, msg
    INT  21h

    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 9.7: Pencarian nilai maksimum array — menggabungkan LOOP, CMP, JNG, dan JMP implisit.

Trace Eksekusi (Langkah demi Langkah)

IterasiCXSIarray[SI]BX (maks)CMPAksi
Awal703434Inisialisasi
172783478 > 34Update BX = 78
264127812 ≤ 78Tidak update
356957895 > 78Update BX = 95
448639563 ≤ 95Tidak update
5310419541 ≤ 95Tidak update
6212899589 ≤ 95Tidak update
7114279527 ≤ 95Tidak update
Selesai01495Maks = 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: <40

    MOV  AL, nilai          ; ambil nilai

    CMP  AL, 80             ; nilai ≥ 80?
    JAE  grade_A

    CMP  AL, 70             ; nilai ≥ 70?
    JAE  grade_B

    CMP  AL, 55             ; nilai ≥ 55?
    JAE  grade_C

    CMP  AL, 40             ; nilai ≥ 40?
    JAE  grade_D

    ; Jika sampai sini: nilai < 40
    MOV  grade, 'E'
    JMP  selesai

grade_A:
    MOV  grade, 'A'
    JMP  selesai

grade_B:
    MOV  grade, 'B'
    JMP  selesai

grade_C:
    MOV  grade, 'C'
    JMP  selesai

grade_D:
    MOV  grade, '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
.stack 100h

.data
    bilangan dw 15, 22, 33, 44, 55, 66, 77, 88, 99, 100
    n        dw 10
    jml_genap dw 0

.code
mulai:
    MOV  AX, @data
    MOV  DS, AX

    MOV  CX, n             ; counter = 10
    MOV  SI, 0             ; index array
    MOV  BX, 0             ; BX = penghitung genap

cek_genap:
    MOV  AX, bilangan[SI]  ; ambil bilangan
    TEST AX, 0001h         ; cek bit 0
    JNZ  ganjil            ; bit 0 = 1 → ganjil, lewati
    INC  BX                ; bit 0 = 0 → genap, tambah counter

ganjil:
    ADD  SI, 2             ; maju ke word berikutnya
    LOOP cek_genap         ; ulangi

    MOV  jml_genap, BX      ; simpan hasil: 5

    MOV  AH, 4Ch
    INT  21h

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

KondisiSignedUnsignedSingle FlagFlag 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?

2. Setelah instruksi CMP AL, 5 dieksekusi dan AL berisi 5, flag apa yang pasti bernilai 1?

3. Instruksi jump mana yang tepat untuk memeriksa "jika AL ≥ BL" untuk bilangan bertanda (signed)?

4. Berapa kali loop berikut dieksekusi? MOV CX, 3 │ label: ... │ LOOP label

5. Apa fungsi instruksi TEST AX, AX?

6. Setelah CMP AX, BX, dengan AX = 0002h dan BX = 0005h, instruksi jump mana yang TIDAK akan melompat?

7. JCXZ label akan melompat ketika...

8. LOOPE label sama dengan...