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.
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!MOVAL, src[0]
MOV dst[0], ALMOVAL, src[1]
MOV dst[1], AL; ... 98 baris lagi ...
Atau dengan loop: 3 instruksi × 100 iterasi = 300 instruksi
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.
Register
Peran
Diubah Oleh
Harus 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):
ABCDE
src=0, dst=2. CLD: salin A→D, lalu B→E, tapi A sudah tertimpa! Hasil: DDE
Solusi (STD — proses dari belakang):
ABCDE
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 forwardMOVDI, OFFSET buffer ; DI = alamat tujuanMOVCX, 100; 100 byteXORAL, AL; AL = 0REPSTOSB; 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 satuCLDMOVSI, OFFSET pesan
MOVCX, panjangcetak_loop:LODSB; AL ← [SI], SI++MOVDL, AL; DL = karakterMOVAH, 02h; cetak karakterINT21hLOOPcetak_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 2REPMOVSB; salin CX byte dari [DS:SI] ke [ES:DI]REPMOVSW; salin CX word dari [DS:SI] ke [ES:DI]REPSTOSB; isi CX byte di [ES:DI] dengan ALREPSTOSW; 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 Berhenti
REPE CMPSB
REPNE SCASB
ZF = 1
Semua byte sama (match)
Karakter ditemukan (found)
ZF = 0
Ketemu perbedaan (mismatch)
Karakter tidak ditemukan (not found)
CX = 0 dan ZF = 1
String sama persis
Karakter ada di byte terakhir
CX = 0 dan ZF = 0
Bedanya di byte terakhir
Tidak 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
CLDMOVSI, OFFSET str1 ; sourceMOVDI, OFFSET str2 ; destination (di ES)MOVCX, panjangREPECMPSB; bandingkan byte per byte; Cek hasil:JZsama; 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
CLDMOVDI, OFFSET kalimat ; string di ES:DIMOVCX, panjang; batas pencarianMOVAL, ' 'REPNESCASB; cari sampai ketemu atau CX habisJZketemu; ZF=1 → spasi ditemukan; ZF=0 → tidak ditemukan dalam CX byte pertamaketemu:; 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
.stack100h.data
src_str db'SELAMAT DATANG DI MATKUL MIKROPROSESOR$'
len equ $ - src_str - 1 ; panjang tanpa '$'
dst_str db40dup(?) ; buffer tujuan
msg_src db'Source: $'
msg_dst db0Dh, 0Ah, 'Copy : $'.codemulai:MOVAX, @dataMOVDS, AXMOVES, AX; ES = DS (penting!); === Salin string menggunakan REP MOVSB ===CLD; arah forwardMOVSI, OFFSET src_str ; sourceMOVDI, OFFSET dst_str ; destinationMOVCX, len; jumlah byteREPMOVSB; Tambahkan '$' di akhir string tujuanMOVBYTE PTR [DI], '$'; Tampilkan sourceMOVAH, 09hLEADX, msg_src
INT21hLEADX, src_str
INT21h; Tampilkan copyLEADX, msg_dst
INT21hLEADX, dst_str
INT21hMOVAH, 4ChINT21hend 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
.stack100h.data
buffer db20dup(?) ; 20 byte buffer
msg db'Buffer diisi: $'.codemulai:MOVAX, @dataMOVDS, AXMOVES, AX; === Isi buffer dengan karakter '*' ===CLDMOVDI, OFFSET buffer
MOVCX, 20; 20 byteMOVAL, '*'REPSTOSB; isi 20 byte dengan '*'; Tambahkan terminator '$' setelah bufferMOVBYTE PTR [DI], '$'; TampilkanMOVAH, 09hLEADX, msg
INT21hLEADX, buffer
INT21h; === Isi ulang dengan nol (clear buffer) ===MOVDI, OFFSET buffer
MOVCX, 20XORAL, AL; AL = 0REPSTOSB; clear bufferMOVAH, 4ChINT21hend mulai
Kode 11.6: Mengisi buffer dengan karakter (STOSB) lalu mengosongkannya — setara dengan memset() di C.
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
.stack100h.data
kalimat db'MIKROPROSESOR MENARIK$'
len equ $ - kalimat - 1
msg_f db'Karakter ditemukan di posisi: $'
msg_nf db'Karakter tidak ditemukan.$'
posisi dw0.codemulai:MOVAX, @dataMOVDS, AXMOVES, AX; === Cari huruf 'M' ===CLDMOVDI, OFFSET kalimat
MOVCX, lenMOVAL, 'M'REPNESCASB; cari 'M'JNZtidak_ketemu; ZF=0 → tidak ditemukan; Hitung posisi: len - CX (karena CX sudah didecrement)MOVBX, lenSUBBX, CX; BX = posisi (1-based)MOVposisi, BX; Tampilkan pesan ditemukanMOVAH, 09hLEADX, msg_f
INT21h; Tampilkan posisi (konversi angka ke ASCII — disederhanakan)MOVAX, posisiAAM; AL = puluhan, AH = satuanADDAX, 3030h; konversi ke ASCIIMOVDL, AHPUSHAXMOVAH, 02hINT21hPOPAXMOVDL, ALMOVAH, 02hINT21hJMPselesaitidak_ketemu:MOVAH, 09hLEADX, msg_nf
INT21hselesai:MOVAH, 4ChINT21hend 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
.stack100h.data
teks db'hello world$'
len equ $ - teks - 1
msg db0Dh, 0Ah, 'Uppercase: $'.codemulai:MOVAX, @dataMOVDS, AX; === Ubah huruf kecil ke huruf besar (in-place) ===CLDMOVSI, OFFSET teks
MOVCX, lenupper_loop:LODSB; AL ← [SI], SI++CMPAL, 'a'JBsimpan; di bawah 'a' → bukan huruf kecilCMPAL, 'z'JAsimpanSUBAL, 20h; konversi: 'a'-'z' → 'A'-'Z' (kurangi 20h)simpan:MOV [SI-1], AL; simpan kembali (SI sudah +1, jadi SI-1)LOOPupper_loop; Tampilkan hasilMOVAH, 09hLEADX, msg
INT21hLEADX, teks
INT21hMOVAH, 4ChINT21hend 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
Instruksi
Operasi
Source
Dest
Pointer
Prefix 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]?
MOVSB menyalin byte dari [DS:SI] ke [ES:DI]. LODSB memuat dari [DS:SI] ke AL. STOSB menyimpan AL ke [ES:DI]. SCASB membandingkan AL dengan [ES:DI].
2. Prefix repetisi mana yang digunakan bersama STOSB untuk mengisi blok memori?
REP STOSB mengulang STOSB sebanyak CX kali. REPE/REPNE tidak relevan untuk STOSB karena STOSB tidak mempengaruhi ZF — prefix tersebut hanya berguna untuk CMPSB dan SCASB yang mengubah ZF.
3. Instruksi mana yang menyetel Direction Flag ke 0 (forward)?
CLD (CLear Direction flag) menyetel DF = 0, sehingga SI/DI di-increment setelah operasi string. STD (SeT Direction flag) menyetel DF = 1 (decrement).
4. Setelah LODSB dieksekusi dengan DF=0, apa yang terjadi pada SI dan AL?
LODSB melakukan: AL ← [DS:SI], lalu SI ← SI + 1 (jika DF=0). Jadi AL mendapat nilai di alamat SI sebelum increment. SI bertambah 1 karena LODSB bekerja per byte.
5. REPE CMPSB berhenti saat kondisi apa?
REPE (Repeat while Equal) terus mengulang selama CX ≠ 0 DAN ZF = 1. Berhenti ketika salah satu kondisi tidak terpenuhi: CX habis ATAU ZF = 0 (ketemu perbedaan).
6. Untuk mencari karakter 'A' dalam string 100 byte, instruksi mana yang paling tepat?
REPNE SCASB mencari byte di AL dalam string yang ditunjuk ES:DI, berhenti saat ketemu (ZF=1) atau CX habis. MOVSB untuk menyalin, STOSB untuk mengisi, CMPSB untuk membandingkan dua string.
7. MOVSB dan MOVSW, apa perbedaannya?
MOVSB menyalin 1 byte dan mengubah SI/DI sebesar ±1. MOVSW menyalin 1 word (2 byte) dan mengubah SI/DI sebesar ±2. Pemilihan tergantung apakah data berupa byte atau word.
8. Jika DF=1 dan SI=0100h, setelah satu kali MOVSB, nilai SI menjadi...
DF=1 berarti decrement. MOVSB mengurangi SI sebesar 1 (karena operasi per byte). Jadi SI = 0100h − 1 = 00FFh.