Chapter 3
Addressing Modes
INTRODUCTION]
Pengembangan perangkat lunak yang efisien untuk mikroprosesor memerlukan pemahaman yang lengkap tentang mode pengalamatan yang digunakan oleh setiap instruksi. Dalam bab ini, instruksi MOV (memindahkan data) digunakan untuk menjelaskan mode pengalamatan data. Instruksi MOV mentransfer byte atau word data antara dua register atau antara register dan memori pada prosesor 8086 hingga 80286. Pada prosesor 80386 dan yang lebih baru, instruksi MOV dapat mentransfer byte, word, maupun doubleword.
Dalam menjelaskan mode pengalamatan memori program, instruksi CALL dan JUMP digunakan untuk menunjukkan bagaimana alur program dapat dimodifikasi.
Mode pengalamatan data meliputi register, immediate, direct, register indirect, base-plus-index, register-relative, serta base-relative-plus-index pada prosesor 8086 hingga 80286. Pada prosesor 80386 dan yang lebih baru, juga terdapat scaled-index mode untuk mengalamati data di memori.
Mode pengalamatan memori program meliputi program relative, direct, dan indirect. Bab ini juga menjelaskan operasi memori stack sehingga instruksi PUSH dan POP, beserta operasi stack lainnya, dapat dipahami.
CHAPTER OBJECTIVES
-
Menjelaskan cara kerja masing-masing mode pengalamatan data.
-
Menggunakan mode pengalamatan data untuk membentuk pernyataan dalam bahasa assembly.
-
Menjelaskan cara kerja masing-masing mode pengalamatan memori program.
-
Menggunakan mode pengalamatan memori program untuk membentuk pernyataan dalam bahasa assembly maupun bahasa mesin.
-
Memilih mode pengalamatan yang sesuai untuk menyelesaikan suatu tugas tertentu.
-
Merinci perbedaan dalam mengalamati data memori pada operasi real mode dan protected mode.
-
Mendeskripsikan urutan kejadian saat data ditempatkan ke dalam stack atau diambil dari stack.
-
Menjelaskan bagaimana sebuah struktur data ditempatkan di dalam memori dan digunakan melalui perangkat lunak.
DATA-ADDRESSING MODES
Karena instruksi MOV adalah instruksi yang sangat umum dan fleksibel, instruksi ini dijadikan dasar untuk menjelaskan mode pengalamatan data. Gambar 3–1 mengilustrasikan instruksi MOV dan mendefinisikan arah aliran data. Sumber berada di sebelah kanan, sedangkan tujuan berada di sebelah kiri, tepat di samping opcode MOV. (Opcode, atau operation code, memberi tahu mikroprosesor operasi apa yang harus dilakukan.)
Arah aliran ini berlaku untuk semua instruksi dan mungkin terasa janggal pada awalnya. Secara alami, kita beranggapan sesuatu bergerak dari kiri ke kanan, padahal di sini justru dari kanan ke kiri.
Perhatikan bahwa dalam sebuah instruksi, tujuan dan sumber selalu dipisahkan oleh koma. Juga perlu dicatat bahwa transfer memori-ke-memori tidak diizinkan oleh instruksi apa pun, kecuali instruksi MOVS.
Dalam Gambar 3–1, instruksi MOV AX, BX
mentransfer isi word dari register sumber (BX) ke register tujuan (AX). Sumber tidak pernah berubah, sedangkan tujuan selalu berubah. Penting diingat bahwa instruksi MOV selalu menyalin data dari sumber ke tujuan. MOV tidak benar-benar “mengambil” data lalu memindahkannya; yang berubah hanyalah tujuan. Selain itu, register flag tidak terpengaruh oleh sebagian besar instruksi transfer data. Sumber dan tujuan sering disebut operand.
Gambar 3–2 memperlihatkan semua variasi mode pengalamatan data menggunakan instruksi MOV. Ilustrasi ini menunjukkan bagaimana setiap mode pengalamatan data dirumuskan dengan instruksi MOV, sekaligus berfungsi sebagai referensi mode pengalamatan data. Perlu dicatat bahwa mode pengalamatan ini sama untuk semua versi mikroprosesor Intel, kecuali scaled-index addressing mode, yang hanya tersedia pada prosesor 80386 hingga Core2. Mode pengalamatan RIP-relative tidak diilustrasikan karena hanya tersedia pada Pentium 4 dan Core2 ketika dijalankan dalam mode 64-bit.
Mode-mode pengalamatan data tersebut adalah sebagai berikut:
Register Addressing
Pengalamatan Register adalah bentuk pengalamatan data yang paling umum, dan setelah nama-nama register dipahami, ini adalah yang paling mudah digunakan.
Mikroprosesor memiliki register-register berikut yang digunakan dalam pengalamatan register:
-
8-bit: AH, AL, BH, BL, CH, CL, DH, dan DL.
-
16-bit: AX, BX, CX, DX, SP, BP, SI, dan DI.
-
32-bit (80386 ke atas): EAX, EBX, ECX, EDX, ESP, EBP, EDI, dan ESI.
-
64-bit (mode Pentium 4 ke atas): RAX, RBX, RCX, RDX, RSP, RBP, RDI, RSI, serta R8 sampai R15.
Selain itu, beberapa instruksi MOV serta instruksi PUSH dan POP juga dapat menggunakan register segmen 16-bit, yaitu CS, ES, DS, SS, FS, dan GS.
Sangat penting bahwa instruksi menggunakan register yang berukuran sama. Jangan pernah mencampurkan register 8-bit dengan 16-bit, 8-bit dengan 32-bit, atau 16-bit dengan 32-bit, karena hal itu tidak diperbolehkan oleh mikroprosesor dan akan menghasilkan error saat program dirakit. Demikian pula, register 64-bit tidak boleh dicampur dengan register ukuran lain.
Sebagai contoh, instruksi seperti MOV AX, AL
atau MOV EAX, AL
tidak diperbolehkan meskipun sekilas tampak masuk akal, karena ukuran register berbeda. Namun, ada beberapa instruksi khusus yang menjadi pengecualian, misalnya SHL DX, CL
, yang akan dijelaskan lebih lanjut pada bab-bab berikutnya.
Perlu juga dicatat bahwa instruksi MOV tidak memengaruhi flag bit. Flag bit biasanya hanya dimodifikasi oleh instruksi aritmetika atau logika.
Immediate Addressing
Mode pengalamatan data lainnya adalah Immediate Addressing. Istilah immediate menunjukkan bahwa data langsung mengikuti opcode heksadesimal di dalam memori. Perlu diperhatikan juga bahwa data immediate adalah data konstan, sedangkan data yang ditransfer dari register atau lokasi memori adalah data variabel.
Immediate addressing dapat bekerja dengan byte atau word data. Pada prosesor 80386 hingga Core2, immediate addressing juga dapat bekerja dengan doubleword data. Instruksi MOV immediate
menyalin data immediate ke dalam register atau lokasi memori.
Sebagai contoh, instruksi MOV EAX,13456H
akan menyalin nilai konstan 13456H, yang terdapat tepat setelah opcode heksadesimal di memori, ke dalam register EAX. Sama seperti instruksi MOV sebelumnya, data sumber akan menimpa data tujuan.
Dalam bahasa assembly simbolik, beberapa assembler menggunakan tanda # untuk menandai data immediate. Misalnya, MOV AX,#3456H
. Namun, sebagian besar assembler tidak menggunakan tanda #, melainkan langsung menuliskan datanya, seperti MOV AX,3456H
. Dalam buku ini, tanda # tidak dipakai. Assembler populer seperti Intel ASM, Microsoft MASM, dan Borland TASM tidak menggunakan tanda # untuk data immediate, tetapi beberapa assembler lama—misalnya pada sistem pengembangan logika Hewlett-Packard—pernah menggunakannya.
Selain itu, pada operasi 64-bit, instruksi MOV immediate dapat menggunakan bilangan immediate berukuran 64-bit. Contoh instruksinya adalah:
MOV RAX,123456780A311200H
, yang diizinkan dalam mode 64-bit.
Direct Data Addressing
Sebagian besar instruksi dapat menggunakan direct data-addressing mode. Bahkan, direct addressing sering digunakan dalam banyak instruksi pada program yang umum. Ada dua bentuk dasar dari direct data addressing:
-
Direct Addressing, yaitu pengalamatan langsung yang berlaku pada instruksi MOV antara sebuah lokasi memori dan register AL, AX, atau EAX.
-
Displacement Addressing, yaitu pengalamatan dengan displacement (pergeseran nilai konstan) yang dapat diterapkan pada hampir semua instruksi dalam set instruksi.
Pada kedua kasus tersebut, alamat dihitung dengan menjumlahkan displacement dengan default data segment address atau dengan alamat segmen alternatif. Dalam operasi 64-bit, instruksi direct addressing juga dapat digunakan dengan alamat linear 64-bit, sehingga memungkinkan akses ke seluruh lokasi memori.
Direct Addressing. Pada pengalamatan langsung dengan instruksi MOV, data ditransfer antara sebuah lokasi memori di dalam data segment dengan register AL (8-bit), AX (16-bit), atau EAX (32-bit). Instruksi MOV yang menggunakan jenis pengalamatan ini biasanya memiliki panjang 3 byte. (Pada prosesor 80386 dan yang lebih baru, terkadang terdapat prefix ukuran register sebelum instruksi, yang menyebabkan panjang instruksi menjadi lebih dari 3 byte.)
Register Indirect Addressing
Register indirect addressing menggunakan sebuah register yang berisi alamat memori tempat data berada. Dengan kata lain, isi dari register tidak langsung dianggap sebagai data, melainkan sebagai penunjuk alamat memori yang menyimpan data.
Sebagai contoh, instruksi:
akan mengambil isi memori pada alamat yang disimpan di register BX dan menyalinnya ke dalam AX. Jadi, kalau BX = 1000H, maka instruksi tersebut akan mengambil data dari memori di alamat 1000H.
Pada mikroprosesor 8086 hingga 80286, register yang bisa digunakan untuk register indirect addressing adalah BX, BP, SI, dan DI. Pada prosesor 80386 ke atas, berlaku hal yang sama tetapi dapat menggunakan register versi 32-bit (EBX, EBP, ESI, EDI). Sedangkan pada mode 64-bit, instruksi ini bisa menggunakan register 64-bit (RBX, RBP, RSI, RDI, dst.).
Register indirect addressing sering digunakan untuk mengakses data di dalam array atau struktur data, karena register dapat berfungsi sebagai penunjuk (pointer) yang bisa diubah nilainya selama eksekusi program.
Seperti halnya pada mode pengalamatan lain, instruksi MOV tidak mengubah isi register sumber alamat (misalnya BX), melainkan hanya mengambil data dari alamat yang ditunjuk.
Base-Plus-Index Addressing
Base-plus-index addressing mirip dengan register indirect addressing, karena juga mengakses data memori secara tidak langsung.
Pada 8086 hingga 80286, mode pengalamatan ini menggunakan satu register basis (BP atau BX) dan satu register indeks (DI atau SI) untuk menentukan alamat memori. Umumnya, register basis menyimpan alamat awal suatu array memori, sedangkan register indeks menyimpan posisi relatif dari elemen dalam array tersebut.
Perlu diingat bahwa setiap kali BP digunakan untuk mengalamati data memori, maka stack segment register (SS) bersama dengan BP akan membentuk effective address, bukan data segment (DS) seperti umumnya.
Register Relative Addressing
Mode pengalamatan ini menambahkan sebuah displacement (nilai konstan) ke isi dari register base dan register index (BP, BX, DI, atau SI) untuk membentuk effective address.
Sebagai contoh, instruksi:
Pada instruksi ini, alamat yang dihasilkan adalah penjumlahan dari isi register BX, SI, dan konstanta 1000H, sehingga menghasilkan alamat efektif tertentu (misalnya 03100H).
Perlu diingat bahwa BX, DI, atau SI akan merujuk ke data segment (DS), sedangkan BP akan merujuk ke stack segment (SS).
Pada 80386 dan prosesor yang lebih baru, displacement dapat berupa bilangan 32-bit, dan register yang digunakan bisa register 32-bit apa saja (kecuali ESP).
Karena segmen pada real mode hanya berukuran 64 KB, maka displacement yang bisa digunakan pada 8086–80286 terbatas pada 16-bit signed number, yaitu dari –32768 (8000H) sampai +32767 (7FFFH).
Base Relative-Plus-Index Addressing
Mode pengalamatan base relative-plus-index mirip dengan base-plus-index addressing, tetapi selain menggunakan register base dan register index, ia juga menambahkan sebuah displacement (nilai konstan) untuk membentuk alamat memori.
Jenis mode pengalamatan ini sering digunakan untuk mengakses array dua dimensi di memori.
Contoh:
Instruksi:
Pada instruksi ini, displacement sebesar 100H ditambahkan ke isi register BX dan SI untuk membentuk offset alamat di dalam data segment. Jika nilai BX = 1000H dan SI = 30H, maka effective address yang dihasilkan adalah:
Sehingga data akan diambil dari lokasi memori 1130H.
Mode pengalamatan ini dianggap cukup kompleks, sehingga jarang digunakan dalam pemrograman praktis. Namun, mode ini tersedia dan bisa digunakan bila diperlukan, misalnya untuk mengakses data dalam struktur atau array multidimensi.
Pada prosesor 80386 dan yang lebih baru, effective address dapat dihasilkan dari penjumlahan dua register 32-bit ditambah displacement 32-bit, sehingga lebih fleksibel dibandingkan prosesor generasi sebelumnya.
Scaled-Index Addressing
Scaled-index addressing adalah mode pengalamatan data terakhir yang dibahas. Mode ini khusus terdapat pada prosesor 80386 hingga Core2.
Mode ini menggunakan dua register 32-bit, yaitu sebuah base register dan sebuah index register, untuk mengakses memori. Register kedua (index) dikalikan dengan sebuah faktor skala (scaling factor) sebelum ditambahkan ke base register untuk membentuk alamat memori.
Faktor skala yang tersedia adalah 1, 2, 4, atau 8.
-
Skala 1 bersifat implisit, sehingga tidak perlu dituliskan dalam instruksi assembly.
-
Skala 2 digunakan untuk mengakses array berukuran word (16-bit).
-
Skala 4 digunakan untuk mengakses array berukuran doubleword (32-bit).
-
Skala 8 digunakan untuk mengakses array berukuran quadword (64-bit).
Contoh instruksi:
Instruksi ini menggunakan faktor skala 2, sehingga isi register ECX dikalikan 2 sebelum ditambahkan ke register EDI untuk membentuk alamat memori.
-
Jika ECX = 00000000H, maka elemen array word ke-0 diakses.
-
Jika ECX = 00000001H, maka elemen array word ke-1 diakses.
-
Jika ECX = 00000002H, maka elemen array word ke-2 diakses, dan seterusnya.
Dengan demikian, indeks (ECX) diskalakan sesuai ukuran elemen array yang ingin diakses.
Jumlah kombinasi register yang dapat digunakan dengan scaled-index addressing ini sangat besar, karena banyak register yang dapat dijadikan base maupun index.
Selain kombinasi base+index, scaled-index addressing juga bisa diterapkan dengan hanya satu register indeks.
Contohnya:
Instruksi ini mengakses data dari array doubleword dengan indeks yang ditentukan oleh ECX.
Pada mode 64-bit, instruksi semacam ini juga berlaku. Contoh:
Instruksi tersebut akan mengakses elemen array quadword menggunakan register RDX sebagai base dan RCX sebagai indeks yang dikalikan 8.
RIP-Relative Addressing
Mode pengalamatan ini menggunakan instruction pointer register 64-bit (RIP) pada mode 64-bit untuk mengalamati lokasi linear dalam model memori flat.
Namun, inline assembler yang tersedia pada Microsoft Visual tidak menyediakan cara untuk menggunakan mode pengalamatan ini, atau mode pengalamatan 64-bit lainnya. Dengan kata lain, saat ini Microsoft Visual belum mendukung pengembangan kode assembly 64-bit.
Instruction pointer biasanya dituliskan dengan simbol $. Misalnya $+34
berarti alamat 34 byte di depan dari posisi program saat ini. Kemungkinan besar, ketika Microsoft akhirnya menambahkan inline assembler untuk mode 64-bit, RIP-relative addressing akan dituliskan dengan cara seperti itu.
Sebagai catatan, Intel menyediakan compiler dengan inline assembler yang mendukung kode 64-bit.
Data Structures
Struktur data digunakan untuk menentukan bagaimana informasi disimpan di dalam array memori, dan sangat bermanfaat dalam aplikasi yang menggunakan array. Cara mudah memahaminya adalah dengan menganggap struktur data sebagai template (cetakan) untuk data.
Dalam bahasa assembly, awal sebuah struktur ditandai dengan direktif STRUC, sedangkan akhir struktur ditutup dengan ENDS.
Contoh tipikal sebuah struktur data didefinisikan dan digunakan tiga kali dalam Contoh 3–12. Perhatikan bahwa nama struktur muncul baik pada deklarasi STRUC maupun pada pernyataan ENDS. Contoh tersebut memperlihatkan struktur data sebagaimana ditulis dalam kode sumber, tanpa hasil terjemahan (assembled version)-nya.
Program Memory-Addressing Modes
Mode pengalamatan memori program digunakan bersama instruksi JMP (jump) dan CALL. Ada tiga bentuk utama pengalamatan program:
-
Direct
-
Relative
-
Indirect
Bagian ini memperkenalkan ketiga bentuk pengalamatan tersebut, dengan menggunakan instruksi JMP untuk menggambarkan cara kerjanya.
Direct Program Memory Addressing
Direct program memory addressing adalah bentuk pengalamatan yang digunakan banyak mikroprosesor awal untuk semua instruksi jump dan call. Mode ini juga dipakai dalam bahasa pemrograman tingkat tinggi, misalnya instruksi GOTO dan GOSUB pada bahasa BASIC.
Mikroprosesor Intel masih menggunakan bentuk pengalamatan ini, tetapi tidak sesering penggunaan relative dan indirect program memory addressing.
Pada instruksi direct program memory addressing, alamat tujuan disimpan bersama dengan opcode.
Sebagai contoh, jika sebuah program perlu melompat ke lokasi memori 10000H untuk mengeksekusi instruksi berikutnya, maka alamat 10000H akan disimpan setelah opcode di dalam memori.
Relative Program Memory Addressing
Relative program memory addressing tidak tersedia pada semua mikroprosesor generasi awal, tetapi tersedia pada keluarga mikroprosesor Intel ini. Istilah relative berarti berhubungan dengan instruction pointer (IP).
Sebagai contoh, jika instruksi JMP melewati 2 byte berikutnya dalam memori, maka alamat tujuan dihitung relatif terhadap nilai instruction pointer, dengan menambahkan nilai 2 ke IP. Hasil penjumlahan inilah yang menjadi alamat instruksi program berikutnya.
Contoh instruksi relative JMP diperlihatkan pada Gambar 3–15. Instruksi JMP ini berukuran 1 byte, disertai displacement sebesar 1 byte atau 2 byte yang ditambahkan ke instruction pointer:
-
Displacement 1 byte digunakan pada short jump.
-
Displacement 2 byte digunakan pada near jump dan CALL.
Keduanya termasuk intrasegment jumps, yaitu loncatan ke mana pun di dalam code segment yang sama.
Pada 80386 dan prosesor lebih baru, displacement bisa berukuran 32-bit, sehingga instruksi bisa melompat ke lokasi mana pun dalam segmen kode 4 GB.
Instruksi Relative JMP dan CALL memuat displacement bertanda (signed displacement), baik 8-bit atau 16-bit, yang memungkinkan loncatan maju maupun mundur di dalam memori. Pada prosesor 80386 ke atas, displacement bisa berupa 8-bit atau 32-bit.
Assembler secara otomatis menghitung jarak displacement dan memilih format instruksi 1-, 2-, atau 4-byte yang sesuai. Jika jarak terlalu jauh untuk displacement 2-byte pada mikroprosesor 8086–80286, beberapa assembler akan menggantinya dengan direct jump.
-
Displacement 8-bit (short jump) memiliki jangkauan sekitar –128 sampai +127 byte dari instruksi berikutnya.
-
Displacement 16-bit (near jump) memiliki jangkauan sekitar –32.768 sampai +32.767 byte.
-
Pada 80386 ke atas, displacement 32-bit memungkinkan jangkauan penuh 4 GB, tetapi hanya dapat digunakan dalam protected mode.
Indirect Program Memory Addressing
Mikroprosesor juga mendukung beberapa bentuk program indirect memory addressing untuk instruksi JMP dan CALL.
Tabel 3–10 (di buku) memperlihatkan contoh instruksi loncatan tak langsung yang valid. Instruksi ini dapat menggunakan:
-
Register 16-bit apa pun (AX, BX, CX, DX, SP, BP, DI, atau SI).
-
Register dengan pengalamatan relatif ([BP], [BX], [DI], atau [SI]).
-
Register relatif dengan displacement.
Pada 80386 dan prosesor lebih baru, register 32-bit juga bisa digunakan untuk menyimpan alamat tujuan loncatan tidak langsung.
Stack Memory-Addressing Modes
Stack memiliki peranan penting pada semua mikroprosesor. Stack digunakan untuk menyimpan data sementara, serta untuk menyimpan alamat pengembalian (return address) yang digunakan oleh prosedur.
Stack adalah memori dengan prinsip LIFO (last-in, first-out), yang artinya data terakhir yang dimasukkan akan menjadi data pertama yang diambil kembali. Data ditempatkan ke dalam stack dengan instruksi PUSH dan dikeluarkan dengan instruksi POP.
Instruksi CALL juga menggunakan stack untuk menyimpan alamat pengembalian sebuah prosedur, dan instruksi RET (return) akan mengambil alamat tersebut kembali dari stack.
Stack dikelola oleh dua register utama:
-
Stack Pointer (SP atau ESP)
-
Stack Segment Register (SS)
Setiap kali sebuah word data didorong (PUSH) ke dalam stack [lihat Gambar 3–17(a)]:
-
8 bit bagian tinggi (high-order) ditempatkan pada alamat memori yang ditunjuk oleh SP – 1.
-
8 bit bagian rendah (low-order) ditempatkan pada alamat memori yang ditunjuk oleh SP – 2.
-
Setelah penyimpanan, SP akan berkurang 2 sehingga siap menunjuk ke lokasi berikutnya untuk PUSH selanjutnya.
Sebaliknya, ketika data diambil (POP) dari stack, mikroprosesor membaca 8 bit rendah dari alamat yang ditunjuk SP, kemudian 8 bit tinggi dari alamat SP + 1, lalu menambahkan 2 pada SP agar kembali menunjuk ke data berikutnya dalam stack.
Dengan cara ini, stack bertindak sebagai area penyimpanan sementara yang efisien untuk data maupun alamat pengembalian prosedur.
Tidak ada komentar:
Posting Komentar