MIKROKOMPUTER
Program Studi S1 ELINS
DAFTAR ISI
MODUL I
MODUL II
VARIABEL ........................................................................................................................................ 19
MODUL III
INTERUPSI ....................................................................................................................................... 27
MODUL IV
MODUL V
MODUL VI
MODUL VII
PROSEDUR ...................................................................................................................................... 45
MODUL VIII
STACK.............................................................................................................................................. 48
MODUL IX
MAKRO ........................................................................................................................................... 51
MODUL X
Sistem Bilangan
1. Sistem Desimal
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Posisi masing-masing digit sangat penting, misalnya bila kita tempatkan angka
7 pada akhir digit: 547, maka akan terbentuk nilai yang lain dari sebelumnya, seperti
terliha pada ilustrasi berikut.
Catatan penting : tiap angka dalam pangkat nol hasilnya 1, bahkan nol pangkat nol
hasilnya juga 1.
4
2. Sistem Biner
Komputer tidaklah secerdas manusia (atau belum secerdas itu), maka akan
lebih mudah untuk membuat mesin elektronik dengan dua keadaan (state) : on and
off, atau 1 dan 0. Komputer menggunakan sistem biner. Yaitu sistem dengan 2 digit:
0, 1. Maka dengan demikian base-nya adalah 2. Setiap angka digit dalam sistem
biner disebut BIT, setiap 4 bit disebut Nibble, setiap 8 bit disebut Byte, bentuk 2 byte
disebut Word, dan bentuk 2 word disebut Double Word.
Ada duatu aturan untuk menambahkan b pada setiap akhir angka binner,
sehingga dengan cara ini kita dapat mengetahui bahwa 101b adalah angka biner
dengan nilai decimal 5. Sedangkan bila diberikan angka biner 10100101b makan
dapat dikonversi menjadi nilai decimal 165.
3. Sistem Heksadesimal
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
Sehingga dengan demikian basenya adalah 16. Angka heksadesimal lebih sederhana
dan mudah untuk dibaca, serta lebih mudah untuk mengkonversi angka dari sistem
5
biner ke sistem heksadesimal dan sebaliknya, dimana setiap nibble 94 bit) dapat
dikonversi ke digit heksadesimal berdasarkan table berikut.
Terdapat suatu aturan untuk menambahkan “h” disetiap akhir angka heksadesimal,
dengan cara ini dapat diketahui bahwa 5Fh adalah angka heksadesimal dengan nilai
decimal 95. Penambahan “0” (nol) juga diperlukan pada awal angka heksadesimal
yang dimulai dengan huruf (A..F), misalnya 0E120h. Konversi angka heksadesimal
1234h (atau sama dengan nilai decimal 4660) diilustrasikan sebagai berikut.
6
Untuk mengkonversi dari sistem decimal ke sistem yang lain , maka diperlukan
pembagian nilai decimal dengan base dari system yang diingingkan, dan setiap
melakukan operasi pembagian perlu diingatkan nilai hasi bagi (result) dan
menyimpan sisa hasil bagi (remainder), dan proses pembagian ini dilakukan hingga
hasilnya adalah 0, Sisa hasil bagi kemudian digunakan untuk mewakili nilai dalam
sistem. Ilustrasi perubahan nilai dari 39 (base 10) ke sistem heksadesimal (base 16)
digambarkan sebagai berikut.
Seperti yang terlihat pada ilustrasi diatas, didapatkan angka heksdadesimal: 27h.
semua sisa hasil bagi (remainder) berada dibawah angka 10, sehingga dalam kasus
konversi ini tidak menggunakan symbol huruf. Contoh lainnya, mengubah 43868
kebentuk heksadesimal, sebagai berikut.
7
Hasilnya adalah OAB5C, dengan merujuk table konversi yang telah dijelaskan
seblumnya untuk mengubah sisa hasil bagi yang lebih dari 9 ke symbol huruf yang
sesuai. Dengan menggunakan prinsip yang sama, kita dapat mengubah bentuk biner
(menggunakan bilangan 2 sebagai pembagi), atau mengubah ke angka
heksadesimal, dan kemudian mengubahnya ke angka biner menggunakan table
konversi.
Bilangan Bertanda
Tidak ada cara yang meyakinkan apakah byte heksadesimal 0FFh adalah
posistif atau negatif, yang dapat direpresentasikan dengan nilai decimal 255 dan -1.
8 bit dapat digunakan untuk membuat kombinasi sebanyal 256 (termasul nol),
8
sehingga kita dapat dengan mudah menduga bahwa kombinasi 128 pertama (0..127)
akan merepresentasikan bilangan posistif dan kombinasi 128 kemudian (128..255)
akan merepresentasikan bilangan negatif. Bila inign mendapatkan nilai “-5”, kita
harus mengurangi 5 dari kombinasi angka (256), sehingga didapatka 256-5 = 251.
Base Converter mengizinkan kita untuk mengkonversi bilangan dari sistem nilai apa
saja ke sistem nilai lainnya. Ketik nilai di texbox, dan nilai akan secara otomatis
diubah ke semua sistem nilai. Dapat pula dipilih mode dalam nilai 8 bit atau 16 bit.
Misalnya kita ingin menghitung : 0FFFFh*10 + FFFFh. Jika kita check Signed
dan Word, akan didapatkan -17 (karena dievaluasi sebagai (-1) * 16 + (-1). Untuk
membuat kalkulasi dengan nilai Unsigned, jangan check tanda Signed sebagan
evaluasunya menjad 65535 * 16 + 65535 dan seharusnya didapat nilai 1114095. Kita
juga dapat menggunakan base converter untuk mengkonversi digit non-desimal ke
nilai decimal signed, dam melakukan kalkulasi dengan nilai decimal.
10
* perkalian
/ pembagian
% modulus
+ penambahan
- Pengurangan
^ Bitwise XOR
| Bitwire OR
Bahasa Assembly
Bahasa assembly merupakan bahasa pemrograman tingkat rendah.
Diperlukan menguasaan materi pengetahuan mengenai struktur komputer untuk
mengerti bahasa assembly. Model komputer sederhana dapat dilihat Gambar 1
berikut.
CPU 8086 memiliki 8 general purpose register, seperti dijelakan dalam Gambar 2.
Masing-masing register memiliki nama masing-masing.
BP Base Pointer
SP Stack Pointer
Fungsi utama dari register adalah untuk menyimpan variable, atau data. Ukuran
register-register yang disebutkan diatas adalah 16 bit. Register AX, BX, CX, DX terdiri
dari 2 register yang terpisah 8 bit, sebagai contoh jika AX = 0011 0000 0011 1001b,
maka AH = 00110000b dan AL = 00111001b ( “H” menyatakan high dan “L”
menyatakan Low). Oleh karena itu, ketika anda mengubah salah satu register 8 bit
maka register 16 bit juga diperbaharui, dan begit sebaliknya. Begitu pula untuk
register BX, CX, dan DX.
Karena register terletak didalam CPU, maka ia jauh lebih cepat daripada
memori. Pengaksessan lokasi memori memerlukan penggunaan sistem bus,
sehingga memakan waktu lebih lama. Menggakses data dalam register biasanya
membutuhkan waktu. Oleh karena itu, anda harus mencoba untuk menjaga variable
dalam register. Set register sangatlah kecik dan kebanyakan register mempunyai
tujuan khusus yang membatasi penggunaanya sebagai variable, tetapi masih
merupakan tempat yang sangat baik untuk menyimpan data sementara dari suatu
perhitungan.
Register Segmen
Meskipun memungkinkan untuk menyimpan data dalam register segemen, hal ini
bukanlah merupakan ide yang baik. Register segrmen memiliki tujuan yang sangat
khusus – menunjuka pada blok yang diakses dari memori.
Alamat dibentuk oleh 2 register dan disebut alamat yang efektif. Secara default,
register BX, SI dan DI bekerja dengan register segmen DS; BP dan SP bekerja dengan
register segmen SS. General purpose register tidak dapat membentuk alamat efektif
dan juga meskipun BX dapat membentuk alamat efektif, BH dan BL tidak bisa.
- IP penunjuk instruksi
IP register selalu bekerja sama dengan register segmen CS dan ini menunjuk ke
instruksi yang sedang dijalankan. Flag register diubah secara otomatis oleh CPU
setelah operasi matematika, hal ini memungkinakan untuk menentukan jenis
14
hasilnya, dan untuk menentukan kondisi untuk mentransfer control ke bagian laian
dari program tersebut. Umumnya anda tidak dapat mengakses langsung register,
cara anda dapat mengakses AX dan register umum lainnya, tetapi adalah mungkin
untuk mengubah nilai dari register sistem menggunakan beberapa trik yang akan
dipelajari kemudian.
15
Modul I
Akses Memory
Untuk mengakses memori kita dapat menggunakan empat register : BX, SI, DI
dan BP. Dengan menggabungkan register di dalam symbol [ ]. Kita bisa
mendapatkan lokasi memori yang berbeda. Kombinasi ini didukung (mode
pengalamatan)
D8 merupakan penggantian nilai yang terdekat untuk 8 bit signed (misalnya: 22,
55h, -1, dll, ..)
D16 merupakan penggantian nilai yang terdekat untuk 16 bit signed (misalnya:
300, 5517h, -259, dll,,)
Nilai dalam register segmen (CS, DS, SS, ES) disebut segmen, dan nilai dalam
register tujuan (BX, SI, D, BP) disebut offset. Ketika DS berisi nilai 1234h dan SI berisi
nilai 7890h bisa juga dicata bahwa 1234:7890. Alamat fisik akan menjadi 1234h *
10h + 7890h = 19BD0h. jika no ditambahkan ke angka decimal, lalu dikalikan dengan
10 maka 10h = 16, jadi jika 0 ditambahkan ke nilai heksadesimal, maka dikalikan
dengan 16, misalnya:
7h = 7
70h = 7 * 16 = 112
Untuk menyatakan pada compiler tentang tipe data, prefix ini harus digunakan
BYTE PTR – untuk byte
WORD PTR – untuk word (2 byte)
Sebagai contoh
pada kasus tertentu assembler dapat menghitung tipe data secara otomatis.
Instruksi MOV
- Menyalin operan kedua (sumber) ke operan pertama (tujuan)
- Operan sumber dapat menjadi nilai langsung (immediate value), general
purpose register atau lokasi memori
- Register tujuan dapat berupa sebuah general purpose register, atau lokasi
memori
- Kedua operan harus berukuran sama, yang dapat berupa byte atau word.
Instruksi MOV tidak dapat digunakan untuk mengatur nilai dari register CS dan IP.
18
Anda dapat mencopi & paste program diatas code editor, dan tekan tombol
[Compile and Emulate] atau tekan tombol F5 pada keyboard anda. Jendela emulator
seharusnya tampil saat program ini dimuat, klik tombol [Single Step] dan berhatikan
nilai-nilai register.
Sebenarnya program diatas menulis langsung ke video memori, jadi anda dapat
melihat bahwaa MOV merupakan instruksi yang powerful.
19
Modul II
Variabel
name DB value
name DW value
name – kombinasi dari alphanumeric, diawali dengan huruf. Mungkin juga tidak
bernama (maka hanya punya alamt saja)
value – berupa nila numeric yang didukung oleh sistem nilai (heksadesimal, biner,
atau decimal), atau symbol “?” untuk veriabel yang tidak diinisialisasi.
Instruksi MOV digunakan untuk mengnyalin nilai dari sumber ke tujuan. Berikut
contoh lain instruksi MOV
ORG 100h
VAR1 DB 7
VAR2 DW 1234h
20
Tulikan kode diatas pada editor emu8086 dan tekan F5 untuk compile dan memuat
ke emulator, hasilnya seharusnya akan terliha sebagai berikut:
Dapat anda lihat seperti yang dicontohkan, kecuali variable diganti dengan lokasi
actual pada memori. Saat compiler membuat kode mesin, hal tersebut secara
otomatis menggantu semua variable dengan alamat offset. Secara default segment
di load didalam register DS ( jika file .COM nilai yang diload pada register DS di set
sama dengan nilai pada register CS - Code Segment.
Kolom pertama pada memori adalah sebuah offser, kolom kedua adalah
suatu nilai heksadesimal, kolom ketiga adalah nilai decimal, dam yang terakhir
21
adalah karakter ASCII. Compiler tidak case sensitive, jadi “VAR1” dan “var1”
mengacu pada variable yang sama. Offset dari VAR1 adalah 0108h, dan alamat
lengkapnya adalah 0B56h:0108h. offset dari var2 adalah 0109h, alamt lengkapnya
adalah 0B56h:0109. Variable ini bertipe WORD sehingga perlu 2 byte, hal tersebut
diasumsikan bahwa low byte (byte) rendah disimpan pada alamat yang lebih rendah
(lower address), sehingga 34h berada sebelum 12h. dapat anda lihat bahwa ada
suatu instruksi lainnya setelah instruksi RET, ini terjadi karena diassemble tidak tahu
dimana data dimulai, dia hanya memproses nilai dalam memori dan memahami
sebagai instruksi 8086 yang sah, (akan dipelajari kemudian). Anda bahkan dapat
menulis program yang sama menggunakan directif DB.
ORG 100h
DB 0A0h
DB 08h
DB 01h
DB 8Bh
DB 1Eh
DB 09h
DB 01h
DB 0C3h
DB 7
DB 34h
DB 12h
Tulis program diatas dalam source editor. Dan tekan F5 untuk diload kedalam
emulator. Hasilnya seharusnya sama dengan kode diassemble, dan berfungsi sama.
Seperti yang anda duga, compiler hanya mengkonversi source code ke dalam byte,
yang disebut dengan machine code, prosessor hanya mengerti machine code dan
menjalankannya.
ORG 100h adalah directive compiler (yang mengatakan pada compiler bagaimana
menangani source code). Directive ini sangat penting saat kita bekerja dengan
22
variable. Directive tersebut mengatakan pada compile bahwa file executable akan
diload pada alamat offset 100h (256 bytes). Jadi compiler harus menghitung alamat
yang benar untuk semua variable ketika ia akan mengganti nama variable dengan
nama offset. Directive tidak pernah dikonversi ke machine code.
Mengapa file executable diload pada offset 100h? sistem operasi menjaga semua
data tentang program dalam 256 byte pertama dari CS (code segment), seperti
misalnya parameter command line dan sebagainya. Meskipun memang benar hanya
bagi file .COM, file .EXE diload pada offset 0000, dan umumnya menggunakan
segment khusus untuk variable.
Array
Array dapat dilihat dan diterjemahkan sebagai suatu rantai variable. Text string
merupakan contoh dari array byte, masing-masing karakter diwakili sebuah nilai
kode ASCII (0…256), contohnya:
b adalah salinan yang sebenarnya dari array a, ketika compiler melihat string yang
didalam tanda petik, secara otomatis akan mengkonversinya kedalam byte. Gambar
dibawah ini menunjukkan bagian memori dimana array dideklarasikan.
Anda dapat mengakses nilai tiap elemen dalam array menggunakan kurung kotak,
contohnya:
MOV AL, a[3]
Anda juga dapat menggunakan memori index register BX, SI, DI, BP, contohnya:
MOV SI, 3
MOV AL, a[SI]
23
Jika anada perlu mendeklarasikan array yang lebih besar, dapat anda gunakan
operator DUP, syntak DUP:
number DUP (value (s) )
number banyak duplikasi yang akan dibuat (nilai konstan)
value ekspresi yang akan diduplikasi oleh DUP
sebagai contoh:
C DB 5 DUP (9)
C DB 9, 9, 9, 9, 9
Contoh lain;
d DB 5 DUP (1, 2)
d DB 1, 2, 1, 2, 1, 2, 1, 2, 1, 2
Tentu saja kita dapat menggunakan DW sebagai pengganti dari DB, jika diperlukan
untuk menjaga nilai yang lebih besar dari 255 atau lebih kecil dari -128. Namun
demikian , DW tidak dapat digunakan untuk mendeklarasikan string.
Ada suatu instruksi yaitu LEA (Load Effective Address) yang merupakan laternatif dari
operator offset. Baik offset dan LEA dapat digunakan untuk mendapatkan offset
address dari suatu variable. LEA bahkan lebih powerful karena ia juga mendapatkan
alamat dari index variabelnya. Mendapatkan alamat dari suatu variable bisa menjadi
sangat berguna dalam suatu situasi misalnya saat kita akan mengirim parameter ke
suatu prosedur, contohnya;
24
Perlu dicatat bahwa hanya register ini yang dapat digunakan dalam kurung kotak
seperti pointer memori: BX, SI, DI, BP.
Konstanta
Konstanta keberadaanya hampir sama dengan variable, namun keberadaanya hanya
sampai program dikompilasi (assemble). Setelah defenisi sebuah konstanta, nilai
yang ditentukan tidak dapat dirubah. Untuk mendeklarasikan sebuah konstanta
digunakan directif EQU.
MOV AX, 5
Anda dapat melihat variable sementara program yang sedang dieksekusi dengan
memilih “Variabel” dari menu “View” dari emulator.
Untuk melihat array, klik pada variable dan mengeset property Element untuk
ukuran array. Dalam bahasa assembly tidak ada batasan tipe data, maka setiap
variable dapat direpresentasikan sebagai suatu array. Variable dapat dilihat dalam
beberapa sistem nilai.
26
Ekspresi secara otomatis dikonversi, contoh, saat ekspresi dimasukkan: 5+2 akan
dikonversi ke 7 dll.
27
Modul III
Interupsi
Saat ini kita akan membahas pada software interupsi, untuk membuat
software interrupt ada suatu instruksi yaitu INT, syntaknya adalah:
INT value
Dimana value berupa angka antara 0 – 255 (0h – FFh), umumnya kita menggunakan
angka heksadesimal. Anda mungkin berfikir hanya ada 256 fungsi, tapi sebenarnya
kurang tepat. Tiap interupsi masih memiliki subfunction. Untuk menentukan suatu
subfuction, register AH harus diset sebelum memanggil interupsi. Setiap interupsi
hampir memiliki 256 sub fungsi, sehingg total subfungsi yang dimiliki adalah 256 *
256 = 65536. Secara umum register AH yang digunakan, tapi suatu saat register lain
juga dipakai. Pada umumnya register lain digunakan untuk mengirim parameter dan
data ke subfuction.
Contoh berikut ini menggunakan INT 10h subfunction 0Eh untuk mencetak
pesan “Hello!”. Fungsi ini menampilkan karakter dilayar. Compile dan emulator lalu
eksekusi program.
28
29
Modul IV
Library of Common Function
Untuk menggunakan macro diatas, tinggal ketik nama macro dan parameter yang
dibutuhkan, contohnya:
30
Saat compiler memproses kode kita, dia mencari file emu8086.inc untuk macro yang
dideklarasikan dan menggantikannya dengan nama macro dalam kode yang
sebenarnya. Umumnya macro relative bagian yang kecil dalam kode, keseringan
menggunakan macro menyebabkan pengeksekusian kita menjadi besar, penggunaan
prosedur lebih dianjukan untuk optimasi ukuran program. Emu8086.inc juga
mendafeniskan prosedur sebagai berikut.
- PRINT_STRING prosedur untuk mencetak null terminater string pada
posisi kursor saat ini, menerima alamat string dalam register DS:SI. Untuk
menggunakannya deklarasikan DEFINE_PRINT_STRING sebelum directive
END.
- PTHIS Prosedur untuk mencetak null terminated string pada posisi kursor
saat ini (seperti PRINT_STRING), tetapi menerima alamat string dari Stack.
ZERO terminated string yang harus didefenisikan setelah instruksi CALL,
contohnya;
CALL PTHIS
DB ‘Hello Word!’, 0
Untuk menggunakannya deklarasikan: DEFINE_PTHIS sebelum directive END.
31
Include emu8086.inc
ORG 100h
DEFINE_SCAN_NUM
DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS ; required for PRINT_NUM
DEFINE PTHIS
MODUL V
Instruksi aritmatika dan Logika
Setiap instruksi arimatika dan logika berpengaruh pada flag register di prosessor.
Dalam register 16 bit, tiap bit flag disebut flag dan dapat bernilai 1 atau 0
- Carry Flag (CF) – flag ini diset ke 1 jika ada unsigned overflow. Contoh saat
kita menambah byte 255 + 1 (hasilnya tidak dijangkauan 0..255). Saat tidak
ada overflow, flag ini diset 0.
- Zero Flag (ZF) – diset 1 jika hasilnya 0, untul hasil selain 0 flag diberi nilai 0.
- Sign Flag (SF) – diset 1 jika hasilnya negatif, saat hasilnya positif diset ke 0.
Sebenarnya flag ini mengambil nilai dari MSB (Most Significant Byte)
- Overflow Flag (OF) – diset ke 1 saat ada signed overflow, contohnya jika
menambah byte 100 + 50, hasinya tidak diluar -128…127.
- Parity Flag (PF) – diset ke 1 jika ada angka genap dari satu bit dalam hasilnya,
dan di set 0 jika ada angka ganjil. Jika hasilnya berupa word hanya 8 digil low
yang dianalisis.
- Auxiliary Flag (AF) – diset 1 jika unsigned overflow untuk low nibble (4bit)
- Interrupt Enable Flag (IF) – jika flag diset 1 CPU mendapatkan interupsi dari
piranti eksternal
- Direction Flag (DF) - flag ini digunakan oleh beberapa instruksi untuk
memproses rantai data, jika flag diset ke 0 – proses diselesaikan ke depan,
jika flag bernilai 1 proses diselesaikan ke belakang.
34
0 OR 1 = 1
0 OR 0 = 0
Kita dapatkan 1 hanya jika salah satu atau kedua bit operan bernilai 1
- XOR Logika XOR (exclusive OR) antara semua bit dari dua operan
Aturannya:
1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
REG : AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
Memori : [BX], [BX+SI+7], variable, etc...
- Instruks INC, DEC hanya mempengaruhi flag: ZF, SF, OF, PF, AF.
- Instruksi NOT tidak mempengaruhi flag apapun,
NOT = kebalikan untuk setiap bit
- Instruksi NEG hanya mempengaruhi flag CF, ZF, SF, OF, PF, AF.
NEG : membuat operan menjadi negatif (bilangan komplemen 2).
Sebenarnya dicadangkan untuk setiap bit operand an ditambahkan 1, contoh
5 menjadi -5 dan 2 menjadi -2.
37
Modul VI
Aliran Kendali Program
Pengendalian alur program merupakan bagian yang penting. Disini program kita
dapat menentukan keputusan berdasarkan kondisi.
1. Unconditional Jump
Instruksi dasarnya adalah bahwa mengendalikan transfer dari suatu titik ke titik
lainnya didalam program, yaitu instruksi JMP, sintaksnya:
JMP label
Deklarasikan label dalam program, tulis namanya dan tambahkan “:” setelah nama
label, label berupa kombinasi karakter alphanumeric yang tidak dimulai dengan
angka, contoh:
Label2:
a
L1234:
Label dapat dideklarasikan pada baris terpisah atau sebelum instruksi lainnya,
contoh:
X1:
MOV AX, 1
Atau
X2 : MOC AX, 2
Contoh instruksi JMP:
ORG 100h
MOV AX, 5 ; set AX to 5.
MOV BX, 2 ; set BX to 2.
JMP calc ; go to 'calc'.
Back: JMP stop ; go to 'stop'.
calc:
ADD AX, BX ; add BX to AX.
JMP back ; go 'back'.
stop:
RET ; return to operating system.
END ; directive to stop the compiler.
38
Tentu saja ada cara mudah untuk mengkalkulasikan dua angka, tetapi contoh diatas
merupakan contoh yang sudah cukup baik mengenai penggunaan instruksi JMP.
Seperti terlihat dari contoh diatas JMP dapat mentransfer kendali baik secara
forward dan backward. Ia dapat melompat kemanapun dalam code segmen (65536
bytes)
Seperti terlihat ada instruksi yang mengerjakan hal yang sama, perlu diingat bahwa
jika kita mengkompile instruksi JE kita akan mendapatkan disassemble sebagai JX, JC
adalah assembled yang sama dengan JB dan sebagainya, perbedaan mana
39
JNC a
JNB a
JAE a
MOV AX, 4
a: MOV AX, 5
ret
include emu8086.inc
ORG 100h
MOV AL, 25 ; set AL to 25.
MOV BL, 10 ; set BL to 10.
CMP AL, BL ; compare AL - BL.
JE equal ; jump if AL = BL (ZF = 1).
PUTC 'N' ; if it gets here, then AL <> BL,
41
Cobalah contoh diatas dengan angka yang lain untuk AL dan BL, buka flag dengan
mengklik tombol flag, gunakan single step dan lihat yang terjadi. Kita juga dapat
memakai F5 untuk mengcompile ulang dan memuat ulang program ke emulator.
3. Kalang (Loop)
Pada dasarnya loop sama dengan jump, mungkin saja mengkodekan loo tanpa
menggunakan instruksi loop dengan hanya menggunakan jump dan compare dan
memang seperti inilah loop bekerja. Semua instruksi loop menggunakan register CX
untuk menghitung langkah, seperti diketahui register CX memiliki 16 bit dan nilai
maksimum dapat menjangkau 65535 atau 0FFFFh. Bagaimanapun juga dapat saja
meletakkan loop dalam loop sehingga nilai jangkaiannya dapat sebesar 65535 *
65535 * 65535 hingga batas stack RAM penuh. Dimungkinkan menyimpan nilai asli
pada register CX dengan instruksi PUSH CX dan mengembalikannya ke asalnya jika
internal loop berakhir dengan pop CX, contohnya:
42
ORG 100h
MOV BX, 0 ; total step counter
MOV CX, 5
K1 : ADD BX, 1
MOV AL, ‘1’
MOV AH, 0Eh
INT 10h
PUSH CX
MOV CX, 5
K2 : ADD BX, 1
MOV AL, ‘2’
MOV AH, 0Eh
INT 10h
PUSH CX
MOVE CX, 5
K3 : ADD BX, 1
MOV AL, ‘3’
MOV AH, 0Eh
INT 10h
LOOP K3 ; internal in internal loop
POP CX
LOOP K2 ; internal loop
POP CX
LOOP K1 ; external loop
RET
Semua conditional jump memiliki satu batasan yang besar, tidak seperti instruksi
JMP mereka hanya bisa melompat sebesar 127 bytes kedepan dan 128 bytes ke
belekang. Batasan ini dapat diatasi dengan trik
- Ambil instruksi lawan conditional jump dari table diatas lalu jump ke label_x
- Gunakan instruksi JMP untuk melompat ke lokasi yang diinginkan
- Buat label_x setelah instruksi JMP
Contoh:
43
Include “emu8086.inc”
ORG 100h
MOV AL, 5
MOV BL, 5
CMP AL, BL ; bandingkan AL dengan BL
JE EQUAL ; hanya ada 1
JNE NOT_EQUAL ; jump jika al <>bl (zf = 0)
JMP EQUAL
NOT_EQUAL :
ADD BL, AL
SUB AL, 10
XOR AL, BL
JMP SKIP_DATA
DB 256 DUP (0) ; 256byte
SKIP_DATA:
PUTC ‘n’ ; jika disini, maka AL <> BL
JMP STOP ; cetak ‘n’ dan jump ke stop
EQUAL: ; jika disini
PUTC ‘y’ ; maka AL = BL, jadi cetak ‘y’
STOP:
RET
Contoh lainnya, menggunakan metode yang disediakan nilai terdekat dalam label.
Jika nilai terdekat diawali $ maka jump dilakukan, jika tidak compiler menghitung
instruksi dimana jump secara langsung diberikan ke offset, contoh;
ORG 100h
; unconditional jump forward
; skip over next 3 byte + itself
; the machine code of short jump instruction take 2 bytes
JMP $3 + 2
a DB 3 ; 1 byte
b DB 4 ; 1 byte
c DB 4 ; 1 byte
; Conditional jump back 5 bytes
MOV BL, 9
DEC BL ; 2 bytes
44
MODUL VII
PROSEDUR
Prosedur merupakan bagian dari kode yang dapat dipanggil dari program dalam
rangka tugas tertentu. Prosedur membuat program lebih terstruktur dan mudah
dimengerti. Umumnya prosedur mengembalikan ke titik dimana dia dipanggil.
Syntaknya:
name PROC
; here goes the code
; of the procedure …
RET
name ENDP
name - nama prosedur, nama ini harus sama di awal dan di akhir prosedur.
ORG 100h
CALL m1
MOV AX, 2
RET ; return to operating system
m1 PROC
MOV BX, 5
RET ; return to caller.
m1 ENDP
END
46
Contoh diatas memanggil prosedur m1, yang mengerjakan MOV BX, 5, dan kembali
ke instruksi selanjutnya setelah CALL : MOV AX, 2
ORG 100h
MOV AL, 1
MOV BL, 2
CALL m2
CALL m2
CALL m2
CALL m2
RET ; return to operating system.
m2 PROC
MUL BL ; AX = AL * BL.
RET ; return to caller.
m2 ENDP
END
Dalam contoh diatas nilai register AL di update setiap saat prosedur dipanggil,
register BL tetap tidak berubah, jadi algoritma ini menghitung 2 pangkat 4, hasil
akhirnya deregister AX adalah 16 (or 10h). Contoh lainnya, prosedur mencetak
pesan Hello World!:
ORG 100h
LEA SI, msg ; load address of msg to SI.
CALL print_me
RET ; return to operating system.
;========================================================
; this procedure prints a string, the string should be
; null terminated (have zero in the end),the string
; address should be in SI register:
47
print_me PROC
next_char:
CMP b.[SI], 0 ; check for zero to stop
JE stop ;
MOV AL, [SI] ; next get ASCII char.
MOV AH, 0Eh ; teletype function number.
INT 10h ; using interrupt to print a char in
; AL.
ADD SI, 1 ; advance index of string array.
JMP next_char ; go back, and type another char.
stop:
RET ; return to caller.
print_me ENDP
;========================================================
msg DB 'Hello World!', 0 ; null terminated string.
END
Prefix “b.” sebelum [SI] berarti bahwa kita perlu membandingkan byte, bukan word.
Jika kita perlu membandingkan word tambahan prefix “w.”. Jika salah satu operan
pembandingnya berupa register, hal tersebut tidak diperlukan karena compiler tahu
ukuran tiap register.
48
MODUL VIII
STACK
Stack adalah suatu arean di memori yang menyimpan data sementara. Stack
digunakan dengan instruksi CALL untuk menyimpan alamat yang dikembalikan pada
prosedur, instruksi RET mengambil nilai ini dari stack dan mengembalikannya ke
offset. Hamper sama kejadiannya jika instruksi INT memanggil interupsi, dia
menyimpan register flag stack, kode segmen dan offset. Instruksi IRET digunakan
untuk mengembalikan dari pemanggil interupsi. Kita juga dapat menggunakan stack
untuk menyimpan data lainnya, ada dua instruksi yang bekerja dengan stack, yaitu:
PUSH – menyimpan nilai 16 bit dalam stack
POP – mengambil nilai 16 bit dari stack
Catatan :
- PUSH dan POP bekerja dengan nilai 16 bit saja
- PUSH immediate bekerja hanya pada CPU 80186 dan sesudahnya.
49
Stack menggunakan algoritma LIFO ( Last In Fisrt Out), aartinya jika kita dorong nilai
satu per satu ke dalam stack:
1, 2, 3, 4, 5
Nilai pertama yang dapat kita POP adalah 5, lalu 4, 3, 2, dan terakhir 1.
Jumlah yang di PUSH dan di POP harus sama. Jika tidak stack akan corrupted dan
tidak dapat kembali ke OS. Kita gunakan instruksi RET untuk kembali ke OS. Jadi jika
program mulai ada alamat yang dikembalikan di stack (umumnya 0000h). instruksi
PUSH dan POP berguna karena tidak memiliki cukup register untuk dioperasikan,
triknya adalah:
- Simpan nilai original dari register dalam stack ( dengan PUSH)
- Pakai register untuk tujuan apapun
- Kembalikan nilai original register dari stack (dengan POP)
Contoh:
ORG 100h
MOV AX, 1234h
PUSH AX ; store value of AX in stack.
MOV AX, 5678h ; modify the AX value.
POP AX ; restore the original value of AX.
RET
END
50
ORG 100h
MOV AX, 1212h ; store 1212h in AX.
MOV BX, 3434h ; store 3434h in BX
PUSH AX ; store value of AX in stack.
PUSH BX ; store value of BX in stack.
POP AX ; set AX to original value of BX.
POP BX ; set BX to original value of AX.
RET
END
Pertukaran terjadi karena stack memakai algoritma LIFO (Last In First Out). Jadi saat
kita PUSH 1212h dan kemudaian 3434h, pada saat POP kita mendapatkan yang
pertama 3434 kemudian 1212h. Area memori stack diset oleh register SS (Stack
Segment) dan register SP (Stack Pointer). Umumnya OS mengatur nilai register ini
saat program dimulai.
“PUSH Source” instruksi ini mengerjakan
- Kurangi 2 dari register SP
- Tulis nilai source ke alamat SS:SO
“POP destination” instruksi ini mengerjakan:
- Tulis nilai alamat SS:SP ke destination
- Tambahkan 2 ke register SP
Alamat sekarang ditunjuk oleh SS:SP yang dinamakan the top of the stack. Untuk file
.COM stack segment dapa umumnya berada di code segment,, dan stack pointer
diset pada nilai 0FFFEh. Pada alamat SS:0FFFE disimpan alamat kembalian untuk
instruksi RET yang dieksekusi pada akhir program. Klik tombol [Stack] pada emulator
window. Bagian atas stack ditandai dengan “<”.
51
MODUL IX
MAKRO
Macro hampir mirip dengan prosedur, tetapi bedanya ia hanya ada hingga kode
dikompilasi, setelah kompilasi dilakukan semua makro akan diganti dengan instruksi
mesin. Jika kita mendeklarasikan macro dan tidak pernah menggunakannya dalam
kode, compiler akan mengabaikannya. Emu8086,unc merupakan salah satu contoh
bagaimana macro dapat dipakai, file ini berisi beberapa macro untuk mempermudah
pengkodean kita
Definisi Macro:
name MACRO [parameter …]
<instruction>
ENDM
Tidak seperti prosedur, macro harus didefenisikan diatas kode yan akan
memakainya, contoh:
ORG 100h
MyMacro 1, 2, 3
MyMacro 4, 5, DX
RET
Macro akan diperluas secara langsung dalam kode, sehingga jika ada label
didalam defenisi makro kita akan mendapatkan pesan error “duplicate
declaration” saat macro dipakai dua kali atau lebih. Untuk menghindari ini
digunakan directive LOCAL diikuti nama variabelnya, nama label atau prosedur,
contoh :
MyMacro2 MACRO
LOCAL label1, label2
CMP AX, 2
JE label1
53
CMP AX, 3
JE label2
label1:
INC AX
label2:
ADD AX, 2
ENDM
ORG 100h
MyMacro2
MyMacro2
RET
MODUL X
PENGENDALIAN PIRANTI EKSTERNAL
Ada 7 piranti yang dilampirkan pada emulator: traffic light, stepper – motor,
LED display, thermometer, printer, robot dan simple test. Kita dapat melihanya
dengan menklik menu “Virtual Devices” dari emulator. Secara umum, dimungkinkan
menggunakan CPU keluarga X86 untuk mengendalikan semua piranti. Perbedaannya
berada pada nomor Port I/O, ini dapat dimodifikasi menggunakan peralatan
elektronik. Biasanya file “.bin” dituliskan ke dalam chip Read Only Memory (ROM),
sistem membaca program dari chip, dan memuat ke RAM dan menjalankan sebagai
program. Prinsip ini digunakan untuk peralatan modern lainnya seperti micro-wave
oven dan lainnya.
Traffic Light
Biasanya untuk mengendalikan lampu lalu lintas, suatu array nilai digunakan. Nilai
dibaca dari array dan dikirim ke port, contohnya:
55
name “traffic”
MOV AX, all_red
OUT 4, AX
MOV SI, Offset situation
next:
MOV AX, [SI]
OUT 4, AX
Motor Stepper
Motor dapat melangkah half step dengan memasang pasangan magnet, motor juga
dilangkahkan full step dengan memasang pasangan magnet, yang diikuti oleh
pasangan magnet yang lain dan pada akhirnya diikuti oleh magnet tunggal dan
seterusnya. Cara yang terbaik untuk membuat full step adalah membuat dua half
step.
Half step sama dengan 11.25’
Full ster sama dengan 22.5’
Motor dapat diputar baik secara searah jalum jam maupun berlawanan arah jarum
jam.
Robot