Minggu 11 Pemrograman

Bab 11: Pemrograman String

Mempelajari instruksi-instruksi khusus 8086 untuk operasi string: menyalin, mengisi, memuat, membandingkan, dan mencari karakter secara efisien menggunakan prefix repetisi.

Capaian Pembelajaran Bab Ini

Setelah mempelajari bab ini, mahasiswa mampu menjelaskan mekanisme instruksi string 8086 dan register yang terlibat; menggunakan MOVSB/MOVSW, STOSB/STOSW, LODSB/LODSW, CMPSB/CMPSW, dan SCASB/SCASW dengan prefix repetisi REP, REPE, REPNE; memahami peran Direction Flag; serta menulis program untuk menyalin, mengisi, membandingkan, dan mencari dalam string.

11.1 Mengapa Instruksi String Diperlukan

Manipulasi string (menyalin, membandingkan, mencari karakter) adalah operasi yang sangat umum dalam pemrograman. Bayangkan berapa banyak instruksi yang dibutuhkan untuk menyalin 100 byte menggunakan MOV biasa:

Tanpa Instruksi String

; 100 byte = 300+ instruksi!
    MOV  AL, src[0]
    MOV  dst[0], AL
    MOV  AL, src[1]
    MOV  dst[1], AL
    ; ... 98 baris lagi ...

Atau dengan loop: 3 instruksi × 100 iterasi = 300 instruksi

Dengan Instruksi String

; Cukup 4 instruksi!
    CLD
    MOV  SI, OFFSET src
    MOV  DI, OFFSET dst
    MOV  CX, 100
    REP  MOVSB

5 instruksi untuk 100 byte — jauh lebih ringkas dan efisien

Intel 8086 menyediakan lima kelompok instruksi string yang dirancang khusus untuk operasi ini. Setiap instruksi string bekerja pada satu elemen (byte atau word) per eksekusi, tetapi bisa digabungkan dengan prefix repetisi (REP) untuk mengulang secara otomatis.

MOVSB/W
Salin
STOSB/W
Isi
LODSB/W
Muat
CMPSB/W
Bandingkan
SCASB/W
Cari

11.2 Register yang Terlibat

Semua instruksi string menggunakan kombinasi register berikut. Memahami peran masing-masing adalah kunci untuk menggunakan instruksi string dengan benar.

RegisterPeranDiubah OlehHarus Diinisialisasi
SI Source Index — menunjuk ke byte/word sumber MOVSB/W, LODSB/W, CMPSB/W (±1 atau ±2) YA
DI Destination Index — menunjuk ke byte/word tujuan MOVSB/W, STOSB/W, CMPSB/W, SCASB/W (±1 atau ±2) YA
CX Counter — jumlah pengulangan saat digunakan dengan prefix REP REP, REPE, REPNE (decrement otomatis) YA
AL / AX Akumulator — nilai yang disimpan (STOSB/W), dimuat (LODSB/W), atau dicari (SCASB/W) LODSB/W (diisi), SCASB/W (tidak diubah) Tergantung
DS Data Segment — segmen untuk source [DS:SI] Tidak diubah oleh instruksi string Biasanya sudah
ES Extra Segment — segmen untuk destination [ES:DI] Tidak diubah oleh instruksi string YA (penting!)
DF Direction Flag — menentukan arah SI/DI (0=+, 1=−) CLD (DF=0), STD (DF=1) YA
SOURCE (DS:SI)
[DS:SI]
byte / word sumber
SI auto ±1/±2 →
operasi string
DESTINATION (ES:DI)
[ES:DI]
byte / word tujuan
DI auto ±1/±2 →
CX = counter (REP) AL/AX = nilai (STOS/SCAS) DF = arah (CLD/STD)

Gambar 11.1: Register yang terlibat dalam operasi string. Perhatikan bahwa source selalu DS:SI dan destination selalu ES:DI.

⚠ ES Harus Diinisialisasi! Pada model .model small, DS dan SS sudah diatur otomatis, tetapi ES tidak. Jika Anda tidak mengeset ES sebelum operasi string yang menulis ke [ES:DI], data akan ditulis ke segmen yang salah. Selalu tambahkan MOV ES, DS di awal program jika source dan destination berada di segmen yang sama.

11.3 Direction Flag (CLD / STD)

Direction Flag (DF) adalah bit ke-10 di Flags Register yang menentukan arah pergerakan pointer SI dan DI setelah setiap operasi string.

CLD — Clear Direction Flag

DF = 0 → SI dan DI di-increment

  • MOVSB: SI+1, DI+1
  • MOVSW: SI+2, DI+2
  • Memproses dari alamat rendah ke tinggi (kiri → kanan)
  • ← digunakan dalam 90% kasus
STD — Set Direction Flag

DF = 1 → SI dan DI di-decrement

  • MOVSB: SI−1, DI−1
  • MOVSW: SI−2, DI−2
  • Memproses dari alamat tinggi ke rendah (kanan → kiri)
  • ← digunakan saat overlap

Kapan Harus Pakai STD? — Masalah Overlap

Kasus Aman (CLD — tidak overlap):
src[0] src[1] src[2] dst[0] dst[1] dst[2]
Area tidak tumpang tindih — CLD aman
Kasus Berbahaya (CLD — overlap, dst > src):
A B C D E
src=0, dst=2. CLD: salin A→D, lalu B→E, tapi A sudah tertimpa! Hasil: DDE
Solusi (STD — proses dari belakang):
A B C D E
STD: mulai dari C→E, lalu B→D, lalu A→C. Data asli tidak tertimpa. Hasil: ABC ✓

Aturan praktis: Jika dst > src dan area overlap → gunakan STD (mulai dari belakang). Jika tidak overlap atau dst < src → gunakan CLD (mulai dari depan).

11.4 MOVSB / MOVSW — Menyalin String

Menyalin satu elemen dari [DS:SI] ke [ES:DI], lalu menyesuaikan pointer.

Mekanisme Internal
; MOVSB (byte):
;   [ES:DI] ← [DS:SI]
;   SI ← SI + 1  (jika DF=0) atau SI − 1 (jika DF=1)
;   DI ← DI + 1  (jika DF=0) atau DI − 1 (jika DF=1)

; MOVSW (word):
;   [ES:DI] ← [DS:SI]  (2 byte)
;   SI ← SI + 2  (jika DF=0) atau SI − 2 (jika DF=1)
;   DI ← DI + 2  (jika DF=0) atau DI − 2 (jika DF=1)

Ekivalen dalam Instruksi Biasa

; MOVSB ekivalen: MOV AL, [SI]
MOV [DI], AL
INC SI ; atau DEC SI
INC DI ; atau DEC DI
; MOVSW ekivalen: MOV AX, [SI]
MOV [DI], AX
ADD SI, 2 ; atau SUB SI, 2
ADD DI, 2 ; atau SUB DI, 2

11.5 STOSB / STOSW — Mengisi String

Menyimpan nilai AL (byte) atau AX (word) ke [ES:DI], lalu menyesuaikan DI. Berguna untuk menginisialisasi blok memori (misalnya mengisi dengan nol).

Mekanisme Internal
; STOSB (byte):
;   [ES:DI] ← AL
;   DI ← DI ± 1

; STOSW (word):
;   [ES:DI] ← AX
;   DI ← DI ± 2

; Catatan: SI TIDAK terpengaruh oleh STOSB/STOSW
Contoh: Isi 100 byte dengan nol
    CLD                    ; arah forward
    MOV  DI, OFFSET buffer ; DI = alamat tujuan
    MOV  CX, 100           ; 100 byte
    XOR  AL, AL           ; AL = 0
    REP  STOSB               ; isi 100 byte dengan 00h

Kode 11.1: Mengisi blok memori dengan nol — operasi yang sangat umum (seperti memset di C).

11.6 LODSB / LODSW — Memuat dari String

Memuat satu elemen dari [DS:SI] ke AL (byte) atau AX (word), lalu menyesuaikan SI. Biasanya digunakan tanpa REP karena kita perlu memproses setiap elemen di dalam loop.

Mekanisme Internal
; LODSB (byte):
;   AL ← [DS:SI]
;   SI ← SI ± 1

; LODSW (word):
;   AX ← [DS:SI]
;   SI ← SI ± 2

; Catatan: DI TIDAK terpengaruh oleh LODSB/LODSW

Mengapa LODSB jarang dipakai dengan REP? Karena setiap iterasi LODSB menimpa AL dengan nilai baru — jika kita tidak memproses AL di antara iterasi, nilai sebelumnya hilang. LODSB biasanya digunakan di dalam loop manual di mana setiap nilai diproses (ditampilkan, diubah, dibandingkan, dll).

Contoh: Proses setiap karakter string
; Cetak setiap karakter string satu per satu
    CLD
    MOV  SI, OFFSET pesan
    MOV  CX, panjang

cetak_loop:
    LODSB                    ; AL ← [SI], SI++
    MOV  DL, AL           ; DL = karakter
    MOV  AH, 02h          ; cetak karakter
    INT  21h
    LOOP cetak_loop        ; ulangi CX kali

Kode 11.2: LODSB di dalam loop manual — setiap karakter diproses (dicetak) sebelum iterasi berikutnya.

11.7 Prefix REP — Pengulangan Sederhana

REP adalah prefix yang ditempatkan sebelum instruksi string untuk mengulangnya secara otomatis. Setiap pengulangan mendekrement CX; berhenti saat CX = 0.

Sintaks dan Mekanisme
; Mekanisme REP:
;   1. Jika CX = 0, selesai (tidak ada eksekusi)
;   2. Eksekusi instruksi string
;   3. CX ← CX − 1
;   4. Jika CX ≠ 0, kembali ke langkah 2

REP  MOVSB     ; salin CX byte dari [DS:SI] ke [ES:DI]
REP  MOVSW     ; salin CX word dari [DS:SI] ke [ES:DI]
REP  STOSB     ; isi CX byte di [ES:DI] dengan AL
REP  STOSW     ; isi CX word di [ES:DI] dengan AX

; REP LODSB — jarang berguna (AL tertimpa terus)
; REP CMPSB — tidak ada gunaannya (tanpa cek ZF)
; REP SCASB — tidak ada gunaannya (tanpa cek ZF)

Dua Fakta Penting tentang REP

  • Jika CX = 0, instruksi TIDAK dieksekusi sama sekali. Ini berbeda dengan LOOP yang selalu mendekrement dulu. Jadi MOV CX, 0; REP STOSB tidak menulis apa-apa.
  • REP hanya cocok untuk MOVSB/W dan STOSB/W. Untuk CMPSB/W dan SCASB/W, gunakan REPE/REPNE yang juga memeriksa flag ZF.

11.8 Prefix REPE / REPNE — Pengulangan Bersyarat

Berbeda dengan REP yang hanya mengecek CX, prefix ini juga mengecek flag ZF. Ini penting karena CMPSB dan SCASB mengubah ZF — kita bisa berhenti lebih awal jika menemukan perbedaan atau kecocokan.

REPE / REPZ

Ulangi selama CX ≠ 0 DAN ZF = 1

Berhenti saat: CX = 0 ATAU ZF = 0

Cocok dengan: CMPSB/W

Use case: Bandingkan dua string — berhenti saat ketemu perbedaan

Alias: REPE = REPZ (Repeat while Equal / Zero)

REPNE / REPNZ

Ulangi selama CX ≠ 0 DAN ZF = 0

Berhenti saat: CX = 0 ATAU ZF = 1

Cocok dengan: SCASB/W

Use case: Cari karakter dalam string — berhenti saat ketemu kecocokan

Alias: REPNE = REPNZ (Repeat while Not Equal / Not Zero)
Mekanisme REPE CMPSB
CX = 0?
Ya ↓
Selesai (semua sama)
Tidak →
CMPSB: [DS:SI] vs [ES:DI]
ZF = 0 (beda)?
Ya ↓
Selesai (ketemu beda)
Tidak →
CX--; ulangi ↑

Membaca Hasil Setelah REPE/REPNE

Kondisi Setelah BerhentiREPE CMPSBREPNE SCASB
ZF = 1Semua byte sama (match)Karakter ditemukan (found)
ZF = 0Ketemu perbedaan (mismatch)Karakter tidak ditemukan (not found)
CX = 0 dan ZF = 1String sama persisKarakter ada di byte terakhir
CX = 0 dan ZF = 0Bedanya di byte terakhirTidak ditemukan sama sekali

11.9 CMPSB / CMPSW — Membandingkan String

Membandingkan [DS:SI] dengan [ES:DI] (pengurangan internal tanpa menyimpan hasil), lalu menyesuaikan kedua pointer. ZF diset berdasarkan hasil perbandingan.

Mekanisme Internal
; CMPSB (byte):
;   [DS:SI] − [ES:DI]  (hasil tidak disimpan, hanya flag yang berubah)
;   SI ← SI ± 1
;   DI ← DI ± 1
;   Jika sama: ZF = 1
;   Jika berbeda: ZF = 0

; CMPSW (word): sama tapi 2 byte, SI/DI ± 2
Contoh: Bandingkan dua string
    CLD
    MOV  SI, OFFSET str1   ; source
    MOV  DI, OFFSET str2   ; destination (di ES)
    MOV  CX, panjang        
    REPE CMPSB               ; bandingkan byte per byte

    ; Cek hasil:
    JZ   sama             ; ZF=1 → string identik
    ; ZF=0 → string berbeda, SI dan DI menunjuk ke byte pertama yang berbeda

Kode 11.3: Membandingkan dua string dengan REPE CMPSB. Setelah selesai, periksa ZF untuk menentukan hasilnya.

11.10 SCASB / SCASW — Mencari Karakter dalam String

Membandingkan AL (byte) atau AX (word) dengan [ES:DI], lalu menyesuaikan DI. ZF diset jika ada kecocokan. Biasanya digunakan dengan REPNE untuk mencari karakter pertama yang cocok.

Mekanisme Internal
; SCASB (byte):
;   AL − [ES:DI]  (hasil tidak disimpan)
;   DI ← DI ± 1
;   Jika AL = [ES:DI]: ZF = 1 (ketemu!)
;   Jika AL ≠ [ES:DI]: ZF = 0 (belum ketemu)

; SCASW (word): AX − [ES:DI], DI ± 2

; Catatan: SI TIDAK terpengaruh. Hanya DI yang bergerak.
Contoh: Cari spasi dalam string
    CLD
    MOV  DI, OFFSET kalimat ; string di ES:DI
    MOV  CX, panjang        ; batas pencarian
    MOV  AL, ' '           
    REPNE SCASB               ; cari sampai ketemu atau CX habis

    JZ   ketemu           ; ZF=1 → spasi ditemukan
    ; ZF=0 → tidak ditemukan dalam CX byte pertama

ketemu:
    ; DI sudah menunjuk 1 byte SETELAH karakter yang ditemukan
    ; Untuk mendapat posisi: posisi = CX_sebelum - CX_sekarang - 1
    ; Atau: DEC DI untuk menunjuk ke karakter spasi itu sendiri

Kode 11.4: Mencari karakter dengan REPNE SCASB. Perhatikan bahwa DI menunjuk satu byte setelah karakter yang ditemukan.

Tips: Menghitung Posisi yang Ditemukan. Setelah REPNE SCASB, posisi karakter dalam string dapat dihitung: posisi = panjang_awal − CX. Karena setiap iterasi mendekrement CX, sisa CX menunjukkan berapa byte yang belum diperiksa. Contoh: jika CX awal = 20 dan CX sekarang = 14, karakter ditemukan di posisi 20 − 14 = 6 (indeks 0-based) atau posisi ke-7 (1-based).

11.11 Contoh Program: Menyalin String

Assembly 8086
.model small
.stack 100h

.data
    src_str  db 'SELAMAT DATANG DI MATKUL MIKROPROSESOR$'
    len      equ $ - src_str - 1  ; panjang tanpa '$'
    dst_str  db 40 dup(?)         ; buffer tujuan
    msg_src  db 'Source: $'
    msg_dst  db 0Dh, 0Ah, 'Copy  : $'

.code
mulai:
    MOV  AX, @data
    MOV  DS, AX
    MOV  ES, AX           ; ES = DS (penting!)

    ; === Salin string menggunakan REP MOVSB ===
    CLD                    ; arah forward
    MOV  SI, OFFSET src_str  ; source
    MOV  DI, OFFSET dst_str  ; destination
    MOV  CX, len           ; jumlah byte
    REP  MOVSB               

    ; Tambahkan '$' di akhir string tujuan
    MOV  BYTE PTR [DI], '$'

    ; Tampilkan source
    MOV  AH, 09h
    LEA  DX, msg_src
    INT  21h
    LEA  DX, src_str
    INT  21h

    ; Tampilkan copy
    LEA  DX, msg_dst
    INT  21h
    LEA  DX, dst_str
    INT  21h

    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 11.5: Menyalin string lengkap dengan REP MOVSB. Perhatikan inisialisasi ES = DS dan penambahan '$' setelah salin.

11.12 Contoh Program: Mengisi Blok Memori

Assembly 8086 — Clear buffer dan isi pola
.model small
.stack 100h

.data
    buffer  db 20 dup(?)         ; 20 byte buffer
    msg     db 'Buffer diisi: $'

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

    ; === Isi buffer dengan karakter '*' ===
    CLD
    MOV  DI, OFFSET buffer
    MOV  CX, 20             ; 20 byte
    MOV  AL, '*'            
    REP  STOSB               ; isi 20 byte dengan '*'

    ; Tambahkan terminator '$' setelah buffer
    MOV  BYTE PTR [DI], '$'

    ; Tampilkan
    MOV  AH, 09h
    LEA  DX, msg
    INT  21h
    LEA  DX, buffer
    INT  21h

    ; === Isi ulang dengan nol (clear buffer) ===
    MOV  DI, OFFSET buffer
    MOV  CX, 20
    XOR  AL, AL           ; AL = 0
    REP  STOSB               ; clear buffer

    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 11.6: Mengisi buffer dengan karakter (STOSB) lalu mengosongkannya — setara dengan memset() di C.

11.13 Contoh Program: Membandingkan Dua String

Assembly 8086 — String comparison
.model small
.stack 100h

.data
    str1    db 'HELLO$'
    str2    db 'HELLO$'
    len     equ 5
    msg_eq  db 'String SAMA$'
    msg_ne  db 'String BERBEDA$'

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

    ; === Bandingkan str1 dan str2 ===
    CLD
    MOV  SI, OFFSET str1
    MOV  DI, OFFSET str2
    MOV  CX, len
    REPE CMPSB               ; bandingkan 5 byte

    ; Tentukan hasil
    JZ   sama
    LEA  DX, msg_ne
    JMP  tampilkan

sama:
    LEA  DX, msg_eq

tampilkan:
    MOV  AH, 09h
    INT  21h

    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 11.7: Membandingkan dua string dengan REPE CMPSB — setara dengan strcmp() di C. Coba ubah str2 menjadi "HELLX" untuk melihat hasil "BERBEDA".

11.14 Contoh Program: Mencari Karakter

Assembly 8086 — Cari huruf 'M' dalam string
.model small
.stack 100h

.data
    kalimat db 'MIKROPROSESOR MENARIK$'
    len     equ $ - kalimat - 1
    msg_f   db 'Karakter ditemukan di posisi: $'
    msg_nf  db 'Karakter tidak ditemukan.$'
    posisi  dw 0

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

    ; === Cari huruf 'M' ===
    CLD
    MOV  DI, OFFSET kalimat
    MOV  CX, len
    MOV  AL, 'M'
    REPNE SCASB               ; cari 'M'

    JNZ  tidak_ketemu       ; ZF=0 → tidak ditemukan

    ; Hitung posisi: len - CX (karena CX sudah didecrement)
    MOV  BX, len
    SUB  BX, CX           ; BX = posisi (1-based)
    MOV  posisi, BX

    ; Tampilkan pesan ditemukan
    MOV  AH, 09h
    LEA  DX, msg_f
    INT  21h

    ; Tampilkan posisi (konversi angka ke ASCII — disederhanakan)
    MOV  AX, posisi
    AAM                    ; AL = puluhan, AH = satuan
    ADD  AX, 3030h        ; konversi ke ASCII
    MOV  DL, AH
    PUSH AX
    MOV  AH, 02h
    INT  21h                 
    POP  AX
    MOV  DL, AL
    MOV  AH, 02h
    INT  21h                 
    JMP  selesai

tidak_ketemu:
    MOV  AH, 09h
    LEA  DX, msg_nf
    INT  21h

selesai:
    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 11.8: Mencari karakter dengan REPNE SCASB dan menghitung posisinya — setara dengan strchr() di C.

11.15 Contoh Program: Mengubah Huruf Kecil ke Huruf Besar

Contoh ini mendemonstrasikan penggunaan LODSB dalam loop manual — karena setiap byte perlu diperiksa dan mungkin diubah sebelum diproses lebih lanjut.

Assembly 8086
.model small
.stack 100h

.data
    teks    db 'hello world$'
    len     equ $ - teks - 1
    msg     db 0Dh, 0Ah, 'Uppercase: $'

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

    ; === Ubah huruf kecil ke huruf besar (in-place) ===
    CLD
    MOV  SI, OFFSET teks
    MOV  CX, len

upper_loop:
    LODSB                    ; AL ← [SI], SI++
    CMP  AL, 'a'           
    JB   simpan            ; di bawah 'a' → bukan huruf kecil
    CMP  AL, 'z'
    JA   simpan            
    SUB  AL, 20h           ; konversi: 'a'-'z' → 'A'-'Z' (kurangi 20h)

simpan:
    MOV  [SI-1], AL      ; simpan kembali (SI sudah +1, jadi SI-1)
    LOOP upper_loop

    ; Tampilkan hasil
    MOV  AH, 09h
    LEA  DX, msg
    INT  21h
    LEA  DX, teks
    INT  21h

    MOV  AH, 4Ch
    INT  21h

end mulai

Kode 11.9: UpperCase menggunakan LODSB + CMP + SUB. Perhatikan trik [SI-1] karena LODSB sudah meng-increment SI.

Mengapa SUB AL, 20h Bisa Mengubah Huruf Kecil ke Besar?

Dalam tabel ASCII: 'a' = 61h dan 'A' = 41h. Selisihnya adalah 61h − 41h = 20h. Ini berlaku konsisten untuk semua huruf a-z. Jadi mengurangi 20h dari huruf kecil akan menghasilkan huruf besar yang sesuai. Sebaliknya, menambah 20h mengubah huruf besar ke kecil. Trik ini jauh lebih efisien daripada menggunakan tabel lookup.

11.16 Tabel Ringkasan Instruksi String

InstruksiOperasiSourceDestPointerPrefix Cocok
MOVSB [ES:DI] ← [DS:SI] DS:SI ES:DI SI±1, DI±1 REP
MOVSW [ES:DI] ← [DS:SI] DS:SI ES:DI SI±2, DI±2 REP
STOSB [ES:DI] ← AL — (AL) ES:DI DI±1 REP
STOSW [ES:DI] ← AX — (AX) ES:DI DI±2 REP
LODSB AL ← [DS:SI] DS:SI — (AL) SI±1 Loop manual
LODSW AX ← [DS:SI] DS:SI — (AX) SI±2 Loop manual
CMPSB [DS:SI] − [ES:DI] DS:SI ES:DI SI±1, DI±1 REPE
CMPSW [DS:SI] − [ES:DI] DS:SI ES:DI SI±2, DI±2 REPE
SCASB AL − [ES:DI] — (AL) ES:DI DI±1 REPNE
SCASW AX − [ES:DI] — (AX) ES:DI DI±2 REPNE

☐ Checklist Sebelum Menggunakan Instruksi String

CLD atau STD — DF sudah ditentukan
MOV SI, OFFSET src — source pointer
MOV DI, OFFSET dst — dest pointer
MOV CX, n — counter
MOV ES, DS — ES diinisialisasi
MOV AL, nilai — untuk STOSB/SCASB

11.17 Soal Latihan

Kerjakan soal-soal berikut untuk menguji pemahaman Anda. Klik "Lihat jawaban" setelah mencoba menjawab sendiri.

Soal 1. Apa perbedaan mendasar antara operasi string pada 8086 dibandingkan dengan instruksi MOV biasa untuk menyalin data? Mengapa instruksi string lebih efisien?

Lihat jawaban

Instruksi string pada 8086 (MOVSB, STOSB, dll.) secara otomatis meng-increment atau decrement pointer (SI dan/atau DI) setelah setiap operasi. Dengan loop manual menggunakan MOV, kita membutuhkan minimal 3 instruksi per elemen: MOV data, INC SI, INC DI. Dengan instruksi string + prefix REP, CPU mengeksekusi seluruh operasi tersebut dalam satu siklus mikrooperasi yang lebih efisien. Selain itu, beberapa instruksi string dapat dioptimasi oleh prosesor yang lebih baru (string acceleration).

Soal 2. Mengapa DS:SI digunakan sebagai source dan ES:DI sebagai destination? Mengapa tidak keduanya menggunakan DS?

Lihat jawaban

Penggunaan segmen terpisah (DS untuk source, ES untuk destination) memungkinkan operasi string antar segmen tanpa perlu mengubah DS. Misalnya, kita bisa menyalin data dari segmen data (DS) ke segmen video (ES = B800h untuk mode teks) tanpa mengorbankan akses ke variabel data. Jika keduanya menggunakan DS, kita harus bolak-balik mengubah DS setiap kali mengakses source dan destination — yang tidak efisien dan rawan error.

Soal 3. Jelaskan peran Direction Flag (DF) dalam instruksi string. Kapan harus menggunakan CLD dan kapan STD?

Lihat jawaban

Direction Flag menentukan arah pergerakan pointer SI/DI: DF=0 (CLD) → SI/DI di-increment (bergerak ke alamat tinggi, kiri ke kanan). Digunakan untuk operasi string biasa dari awal ke akhir.
DF=1 (STD) → SI/DI di-decrement (bergerak ke alamat rendah, kanan ke kiri). Digunakan ketika source dan destination overlap dan destination berada di alamat lebih tinggi dari source — agar data yang belum disalin tidak tertimpa. STD juga digunakan saat memproses string dari belakang ke depan.

Soal 4. Apa yang terjadi jika Anda menggunakan REP MOVSB tanpa terlebih dahulu mengatur DF, SI, DI, dan CX? Mengapa ini berbahaya?

Lihat jawaban

Tanpa inisialisasi: (1) DF bisa bernilai 0 atau 1 tergantung instruksi sebelumnya — arah salin tidak terduga, (2) SI bisa menunjuk ke alamat sembarang — data yang disalin bukan data yang dimaksud, (3) DI sama — data ditulis ke lokasi yang salah, bisa menimpa kode atau data penting, (4) CX bisa bernilai apa saja — jika CX sangat besar, operasi akan menulis ke area memori far di luar batas program, menyebabkan crash. Selalu inisialisasi keempatnya sebelum instruksi string.

Soal 5. Tulis program Assembly yang membalikkan sebuah string di tempat (in-place reverse). Misalnya "HELLO" menjadi "OLLEH". Gunakan instruksi string yang sesuai.

Lihat jawaban

Logika: Tukar karakter pertama dengan terakhir, kedua dengan kedua dari belakang, dst. Gunakan LODSB untuk baca dari depan, SCASB tidak cocok di sini, lebih baik gunakan pointer manual atau kombinasi SI/DI.

Kode:
MOV SI, 0 ; pointer depan
MOV DI, panjang-1 ; pointer belakang
MOV CX, panjang/2 ; jumlah tukar
loop_swap:
MOV AL, string[SI]
MOV BL, string[DI]
MOV string[SI], BL
MOV string[DI], AL
INC SI
DEC DI
LOOP loop_swap


Catatan: instruksi string built-in (MOVSB dst.) tidak langsung mendukung swap in-place, jadi di sini loop manual dengan register lebih tepat.

Soal 6. Bandingkan REPE CMPSB dengan REPNE SCASB. Dalam situasi apa masing-masing digunakan? Berikan contoh kasus nyata.

Lihat jawaban

REPE CMPSB membandingkan dua string byte per byte, berhenti saat ketemu perbedaan ATAU CX habis. Digunakan untuk mengecek apakah dua string sama. Contoh: validasi password — bandingkan input user dengan password tersimpan.

REPNE SCASB mencari byte tertentu (di AL) dalam string, berhenti saat ketemu ATAU CX habis. Digunakan untuk mencari karakter dalam string. Contoh: mencari spasi dalam kalimat untuk mengetahui posisi kata pertama, atau mencari karakter null-terminator.

11.18 Kuis Bab 11

Uji pemahaman Anda. Pilih satu jawaban yang paling tepat. Setelah memilih, jawaban benar akan ditandai dan penjelasan muncul.

1. Instruksi string mana yang digunakan untuk menyalin satu byte dari [DS:SI] ke [ES:DI]?

2. Prefix repetisi mana yang digunakan bersama STOSB untuk mengisi blok memori?

3. Instruksi mana yang menyetel Direction Flag ke 0 (forward)?

4. Setelah LODSB dieksekusi dengan DF=0, apa yang terjadi pada SI dan AL?

5. REPE CMPSB berhenti saat kondisi apa?

6. Untuk mencari karakter 'A' dalam string 100 byte, instruksi mana yang paling tepat?

7. MOVSB dan MOVSW, apa perbedaannya?

8. Jika DF=1 dan SI=0100h, setelah satu kali MOVSB, nilai SI menjadi...