Pembentukan Konstanta Secara Assembly
Pembentukan Konstanta Secara Assembly
Assembly listing merupakan salah satu hasil kerja program Assembler yang sangat berguna untuk memahami teknik pemrograman Assembler, bahasan dalam artikel ini memakai Assembly Listing untuk pemahaman pengatur Assembler DB dan DW secara mendalam.
Tujuan akhir penulisan program assembly adalah mengisi memori-program dengan kode-kode mesin yang dipakai untuk mengendalikan mikrokontroler, di samping itu sering diperlukan pula data-data konstan yang harus disimpan ke dalam memori-program.
Untuk keperluan ini semua Assembler dilengkapi dengan pengatur program Assembler (assembler dirictive) untuk mengisi berbagai macam data ke memori-program. Dikenal 2 macam pengatur program Assembler (assembler dirictive), yakni DB (singkatan dari Define Byte) dan DW (Define Word). DB dipakai untuk membentuk data byte demi byte, sedangkan DW dipakai untuk membentuk data 2 byte yang merupakan alamat (nomor memori).
DB – Define Byte untuk Tabel
DB singkatan dari Define Byte, memerintah Assembler agar mengisi memori-program dengan data-data yang tercantum dalam operand. Operand dari perintah DB bisa hanya satu, tapi bisa berapa pun sejauh baris untuk menulis perintah tersebut masih cukup menampung. Seperti biasa kalau terdapat banyak operand, maka operand satu dengan yang lain dipisahkan dengan tanda koma.
DB sering dipakai untuk membentuk tabel dalam memori-program.
Sebagai contoh adalah rangkaian sederhana dalam Gambar 1, dalam contoh ini mikrokontroler dipakai untuk menggantikan IC TTL 7447, yakni Binary to 7 segment Decoder.
Kaki P3.0..P3.3 AT89C2051 dipakai sebagai masukan data biner, kombinasi kedudukan dari skaklar yang dipasangkan pada kaki ini menyatakan angka berapa yang akan ditampilkan pada penampil 7 ruas. Di dalam chip AT89C2051 kaki-kaki P3.0..P3.3 dihubungkan ke sumber tegangan Vcc lewat sebuah tahanan sekitar 5 kOhm, sehingga dalam keadaan saklar terbuka kaki P3.0..P3.3 akan bernilai ‘1’, saklar yang ditutup akan memberi kaki bersangkutan bernilai ‘0’.
Kaki P1.0..P1.6 dipakai untuk menyalakan LED pembentuk tampilan 7 ruas. P1.0..P1.6 yang berfungsi sebagai output, mampu menyalurkan arus ke ground sampai sebesar 20 mA saat output bernilai ‘0’, arus sebesar ini cukup bisa dipakai untuk menyalakan LED dengan terang.
Tampilan 7 ruas yang dipakai adalah Common Anode 7 Segment LED, artinya semua anode dari 7 buah LED dihubungkan jadi satu, dan katode dari masing-masing LED dihubungkan keluar chip. Dengan susunan tampilan 7 ruas LED semacam ini, kalau anode dihubungkan ke sumber tegangan +5V, salah satu katode dari LED dihubungkan ke ground lewat sebuah tahanan (yang berfungsi sebagai pembatas arus yang mengalir), maka LED bersangkutan akan menyala.
Dalam rangkaian Gambar 1 P1.0..P1.6 berfungsi sebagai saklar untuk menyalurkan arus dari sumber tegangan +5V lewat anode-katode salah satu LED yang diserikan dengan tahanan 220 Ohm ke ground. Jadi LED akan menyala kalau salah satu kaki dari P1.0..P1.6 bernilai ‘0’, dan kalau kaki-kaki tersebut bernilai ‘1’ LED tidak akan menyala.
Ruas a dikendalikan dengan P1.0, ruas b dikendalikan dengan P1.1 dan seterusnya ruas g dikendalikan dengan P1.6 dan P1.7 tidak dipakai. Untuk membentuk angka 0 pada tampilan 7 ruas, semua ruas kecuali ruas g menyala, jadi data yang dikeluarkan ke Port 1 adalah %11000000 (angka biner 11000000 – yang bermakna ruas a sampai f menyala, ruas g padam dan P1.7 tidak dipakai).
Selama rangkaian pada Gambar 1 tidak dirubah, angka %11000000 tersebut merupakan sebuah kombinasi yang sudah konstan, dan angka ini diisikan ke dalam memori-program dengan instruksi pada baris 17: DB %11000000.
Assembly Listing untuk baris tersebut adalah 17: 000D C0 DB %11000000. Bisa dijelaskan, 000D adalah nomor memori-program yang akan menampung kode kombinasi ruas untuk menyalakan angka 0, C0 adalah angka biner 1100000 yang ditulis dalam bentuk heksadesimal.
Dengan cara yang sama disusun kombinasi ruas untuk menyalakan angka 1 sampai 9, kemudian dituliskan dalam bentuk DB secara berurutan, seperti terlihat pada baris 18 sampai baris 26. Dengan demikian terbentuknya sebuah tabel yang dinamakan sebagai KombinasiRuas (baris 15).
Program 1 merupakan program lengkap untuk menjadikan rangkaian Gambar 1 sebagai Pengubah kedudukan saklar ke bentuk 7 ruas. Program ini merupakan program utuh, kalau diisikan ke dalam chip AT89C2051 sudah bisa berfungsi sepenuhnya.
Program ini tidak memerlukan variabel dalam memori, dengan demikian program ini tidak pakai perintah .data, hanya pakai .code pada baris 01.
ProgramUtama (baris 03 sampai 08) membaca kedudukan saklar yang terpasang pada Port 3 (baris 04), karena saklar hanya terpasang pada P3.0 sampai P3.3, sedangkan P3.4 sampai P3.7 tidak dipakai, agar tidak mengganggu kerja sub-rutin JadikanRuas nilai P3.4 sampai P3.7 yang terbaca ke dalam A.4 sampai A.7 di-nol-kan dengan instruksi ANL A,#%00001111 pada baris 05. Nilai biner dari kombinasi saklar kini tersimpan di A, nilai tersebut dirubah menjadi kombinasi ruas pada baris 06.
Kombinasi ruas ditampilkan ke Port 1 untuk menyalakan tampilan 7 ruas LED pada baris 07. Pekerjaan di atas diulang terus menerus tanpa akhir dengan instruksi SJMP ProgramUtama pada baris 08.
Tabel KombinasiRuas berada di dalam memori-program, sehingga isi tabel KombinasiRuas diambil dengan instruksi MOVC A,@A+PC (baris 12). Dalam instruksi ini nomor memori yang dipakai dihitung dari nilai PC saat itu ditambah dengan nilai A. Pada saat instruksi itu dilaksanakan, nilai PC adalah 000C (baris 13), tapi tabel KombinasiRuas ada di memori 000D (baris 17) dan seterusnya, dengan demikian terdapat selisih 1 angka, untuk mengatasi hal ini nilai A dikoreksi dulu dengan instruksi INC A pada baris 11.
Misalnya kombinasi saklar pada P3.0..P3.3 adalah 0101 (5), saat sub-rutin JadikanRuas dipanggil nilai A adalah 5, nilai ini dinaikkan 1 menjadi 6 pada baris 16. Saat MOVC A,@A+PC (baris 12) dilaksanakan, nilai PC adalah 000C (baris 13) jadi memori-progam yang isi akan diambil adalah memori-program nomor 000C+5 = 0012. Nomor ini tercantum pada baris 22, yakni baris yang menentukan kombinasi ruas untuk menyalakan angka 5!
Program 1 – Pengubah kedudukan saklar ke bentuk 7 ruas
01: 0000 .CODE
02: 0000 ORG 0
03: 0000 ProgramUtama:
04: 0000 E5 B0 MOV A,P3
05: 0002 54 0F ANL A,#%00001111
06: 0004 11 0A =100A ACALL JadikanRuas
07: 0006 F5 90 MOV P1,A
08: 0008 80 F6 =1000 SJMP ProgramUtama
09: ;
10: 000A JadikanRuas:
11: 000A 04 INC A ; Melompati instruksi RET
12: 000B 83 MOVC A,@A+PC ; Ambil KombinasiRuas
13: 000C 22 RET
14: ;
15: 000D KombinasiRuas:
16: ; -gfedcba
17: 000D C0 DB %11000000 ; 0
18: 000E F9 DB %11111001 ; 1
19: 000F A4 DB %10100100 ; 2
20: 0010 B0 DB %10110000 ; 3
21: 0011 99 DB %10011001 ; 4
22: 0012 92 DB %10010010 ; 5
23: 0013 82 DB %10000010 ; 6
24: 0014 F8 DB %11111000 ; 7
25: 0015 80 DB %10000000 ; 8
26: 0016 90 DB %10010000 ; 9
DB – Define Byte untuk String
Selain untuk membangun tabel seperti yang dibahas di atas, DB dipakai pula untuk membentuk string (teks) seperti terlihat dalam baris 04 sampai baris 12 Potongan Program 2.
Baris 05 membentuk string ‘SBY’, dituliskan sebagai DB ‘SBY’. Harap diperhatikan untuk membentuk string diperlukan tanda petik pada operand, cara ini mirip dengan yang dipakai dalam Pascal. String ini dinamakan sebagai Kota1 (baris 04). Agar sub-rutin untuk mencetak string ini mudah dibuat, string ini diakhiri dengan bilangan heksadesimal 00 (baris 06 – string semacam ini dinamakan sebagai null-string).
Assembly listing pembentukan string ini, 05: 1000 53 42 59 DB ‘SBY’, 1000 menyatakan string ini ditempatkan di memori-program nomor 1000, memori-program tersebut diisi dengan huruf ‘S’ yang diwakili dengan kode ASCII-nya, yakni bilangan heksadesimal 53, berikutnya memori-program nomor 1001 diisi dengan 42 yang indentik dengan huruf ‘B’ dan memori-program nomor 1003 berisi hurus ‘Y’ (59).
Assembly Listing baris berikutnya : 06: 1003 00 DB 0, tulisan 0 dibelakang DB tanpa tanda petik, dengan demikian yang disimpan dalam memori-program nomor 1003 adalah bilangan heksadesimal 00, bukan kode ASCII dari angka 0.
String Kota2 pada baris 08, menghasilkan Assembly Listing yang sedikit berlainan : 08: 1004 53 75 72 DB ‘Surabaya‘,0. Yang tertera di belakang angka 1004 hanya 3 bilangan heksadesimal 53 75 72, pada hal jumlah byte ‘Surabaya’ berikut dengan satu 0 adalah 9, hal ini menimbulkan kesan seolah-olah hanya 3 byte pertama yang ditempatkan dalam memori-program, tapi yang terjadi sesungguhnya bukan demikian, cara penulisan assembly listing semacam ini merupakan penyederhanaan, agar tidak menghabiskan banyak baris untuk menampilkan isi memori-program yang berisi kode ASCII.
Meskipun baris 08 hanya menampilkan 1004 53 75 72 , tapi nomor memori-program baris 09 adalah 100D, artinya memori-program nomor 1004 sampai 100C sebanyak 9 byte dipakai untuk menampung string yang dibentuk pada baris 08.
Potongan Program 2 – Membentuk String
01: 0018=SerialOut EQU $0018 Output A to Serial Port
02: 0000 .CODE
03: 1000 ORG $1000
04: 1000 Kota1:
05: 1000 53 42 59 DB ‘SBY’
06: 1003 00 DB 0
07: 1004 Kota2:
08: 1004 53 75 72 DB ‘Surabaya’,0
09: 100D Kota3:
10: 100D 53 65 6D DB ‘Semarang’,0
11: 1016 Kota4:
12: 1016 4A 61 6B DB ‘Jakarta’,0
13:
14: 101E OutHuruf:
15: 101E 12 00 18 =0018 LCALL SerialOut
16: 1021 OutString:
17: 1021 E4 CLR A
18: 1022 93 MOVC A,@A+DPTR
19: 1023 A3 INC DPTR
20: 1024 70 F8 =101E JNZ OutHuruf
21: 1026 22 RET
Baris 14 sampai baris 21 Potongan Program 2 merupakan sub-rutin untuk mencetak null-string. Jalan masuk ke sub-rutin ini adalah OutString pada baris 16. Sebelum memakai sub-rutin ini DPTR harus diisi dengan nomor memori-program yang berisi null-string yang akan dicetak. Baris 17 CLR A me-nol-kan Akumulator A, agar pada baris 18 nomor memori-program hanya ditentukan oleh nilai yang tersimpan dalam DPTR.
Agar DPTR selalu siap untuk pengambilan huruf berikutnya, setelah dipakai untuk mengambil isi memori-program nilai DPTR dinaikan 1 pada baris 19. String yang di baris 03 sampai baris 12 adalah null-string yang diakhiri dengan bilangan heksadesimal 00, huruf terakhir dari string ini diperiksa pada baris 20, kalau huruf yang baru saja diambil bukan 00 maka program dialirkan ke OutHuruf yang berfungsi mencetak huruf pada baris 14.
Baris 01: 0018=SerialOut EQU $0018, mendefinisikan SerialOut sebagai $0018, dalam hal ini dipakai pengatur program Assembler (assembler dirictive) EQU (singkatan dari Equal).
Setelah ditentukan dengan EQU, berikutnya assembler akan mengganti SerialOut menjadi $0018, seperti terlihat pada baris 15: 101E 12 00 18 =0018 LCALL SerialOut.
DW – Define Word
Define Word (DW) merupakan pengatur program Assembler (assembler dirictive) untuk mengisi memori-program seperti DB, tapi yang diisikan adalah nomor memori yang panjangnya 2 byte, seperti terlihat dalam baris 27 sampai 30 pada Program 3.
Assembly Listing 27: 0039 13 00 DW Kota1, diartikan sebagai berikut : memori-program yang diisi mulai nomor 0039, bilangan heksadesimal 00 di 003A dan bilangan heksadesimal 13 di 0039, kedua bilangan itu secara bersama merupakan nomor memori-program dari string Kota1 (lihat baris 16 Kota1 terletak di 0013). Hanya saja urutan penulisan alamatnya (0013) terbalik, bukan ditulis sebagai 00 dan 13 tapi ditulis sebagai 13 dan 00.
Kota2, Kota3 dan Kota4 ditabelkan bersama Kota1(baris 28; 29 dan 30) dalam tabel yang dinamakan sebagai TabelKota (baris 26), sehingga bisa dikatakan isi tabel nomor 0 adalah alamat string Kota1, isi tabel nomor 1 adalah alamat string Kota2 dan seterusnya.
Rangkaian Gambar 2 dibangun untuk mendemonstrasikan pemakaian TabelKota yang dibahas di atas. Program 3 merupakan program lengkap untuk mengendalikan rangkaian tersebut.
Port RS232 P1 dalam Gambar 3, dihubungkan ke port seri PC dengan kecepatan 9600 baud, pada PC dijalankan program HyperTerminal dari Windows. Rangkaian Gambar 3 akan terus menerus mengirimkan salah satu nama kota yang tercantum dalam Program 3, yaitu ‘Surakarta’, ‘Jakarta’, ‘Semarang’ atau ‘Surabaya’.
Nama kota yang dikirim alat ini, ditentukan oleh kedudukan saklar S0 dan S1 yang terhubung pada P3.2 dan P3.3. Kombinasi 00 dari saklar S1–S0 memilih ‘Surakarta’, kombinasi 01 memilih ‘Jakarta’ dan seterusnya.
Program ini mulai dari memori-program nomor 0000 (baris 02), setelah reset AT89C2051 akan mengerjakan instruksi-instruksi baris 02 sampai 07 satu kali, kemudian terus menerus mengerjakan ProgramUtama (baris 09 sampai 15), selama itu rangkaian ini secara terus menerus mengirim string nama kota ke PC yang diterima oleh HyperTerminal dan ditampilkan pada layar PC.
Karena program ini memakai port seri untuk mengirim string ke PC, sebelum mengirim data, terlebih dulu harus diatur tata kerja port seri dalam chip AT89C2051. Baris 03 sampai 05 mengatur kecepatan pengiriman (baud rate) port seri yang ditentukan oleh Timer 1, baris 03 menentukan Timer 1 bekerja pada mode 2, yakni sebagai Pencacah Biner 8 bit dengan Isi Ulang, faktor pembagi Timer 1 ditentukan 3 (ditulis sebagai -3 pada baris 04), angka ini disesuaikan dengan kristal yang dipakai sebesar 11.059 MHz untuk menghasilkan kecepatan 9600 Baud. Baris 05 memerintah AT89C2051 mulai menjalankan Timer 1 untuk keperluan port seri.
Tata kerja port seri AT89C2051 ditentukan dengan cara mengatur isi register SCON. Pada baris 07 ditentukan port seri AT89C2051 bekerja pada mode 1, yakni sebagai UART (Universal Asynchronous Receiver/Transmitter) yang kerjanya sesuai dengan port Seri PC. Dan juga menyatakan port seri siap mengirim data (TI=1) serta mengaktipkan sistem penerimaan data port seri (REN=1, rangkaian Gambar 1 tidak dipakai untuk menerima data, sesungguhnya REN tidak dibuat menjadi ‘1’ pun rangkaian tetap bekerja dengan baik).
Setelah baris 07, port seri siap dipakai untuk mengirim maupun menerima data. Pengiriman data dilakukan dengan 3 instruksi pada baris 59; 60 dan 61. Baris 59 JNB TI,$, menunggu TI menjadi ‘1’, artinya menunggu port seri selesai mengirimkan data yang dikirim sebelumnya, setelah TI=’1’ data dikirim dengan instruksi MOV SBUF,A pada baris 60, dan baris 61 CLR TI menyatakan port seri sedang sibuk mengirim data baru.
ProgramUtama membaca kedudukan saklar pemilih string yang dipasang pada P3.2 dan P3.3 (baris 10), agar nilai bit P3.0, P3.1 dan P3.4..P1.7 yang ikut terbaca dengan instruksi MOV A,P1 tidak mengganggu kerja sub-rutin PilihString bit-bit ini di-nol-kan dengan instruksi ANL A,#%00001100 (baris 11).
Karena saklar S0 dan S1 tidak diletakan pada P3.0 dan P3.1, maka hasil pembacaan di atas tidak mewakili nomor secara biner, untuk mengatasi masalah ini nilai A digeser ke kanan 2 kali (baris 12 dan 13).
Kini nomor string yang dipilih disimpan di A, nomor ini dipakai untuk memilih string dan mengirimkannya ke port seri lewat sub-rutin PilihString (baris 32). Instruksi SJMP ProgramUtama pada baris 15 mengulang ProgramUtama tanpa henti.
Program 3 – Memilih String
01: 0000 .CODE
02: 0000 ORG 0
03: 0000 75 89 20 MOV TMOD,#%00100000 ; T1 = 8 bit auto-reload
04: 0003 75 8D FD MOV TH1,#-3 ; Nilai isi ulang Timer1
05: 0006 D2 8E SETB TR1 ; hidupkan Timer 1
06:
07: 0008 75 98 52 MOV SCON,#%01010010 ; Mode 1, REN=1, TI=1
08:
09: 000B ProgramUtama:
10: 000B E5 B0 MOV A,P3 ; baca kedudukan saklar
11: 000D 54 0C ANL A,#%00001100 ; ambil bit 2 & bit 3 saja
12: 000F 03 RR A ; pindahkan bit 2 & bit 3
13: 0010 03 RR A ; ke bit 0 & bit 1
14: 0011 11 41 =0041 ACALL PilihString ; Pilih dan cetak string
15: 0013 80 F6 =000B SJMP ProgramUtama
16:
17: 0015 Kota1:
18: 0015 53 75 72 DB ‘Surakarta’,0
19: 001F Kota2:
20: 001F 4A 61 6B DB ‘Jakarta’,0
21: 0027 Kota3:
22: 0027 53 65 6D DB ‘Semarang’,0
23: 0030 Kota4:
24: 0030 53 75 72 DB ‘Surabaya’,0
25:
26: 0039 TabelKota:
27: 0039 15 00 DW Kota1
28: 003B 1F 00 DW Kota2
29: 003D 27 00 DW Kota3
30: 003F 30 00 DW Kota4
31:
32: 0041 PilihString:
33:
34: ; ***** Menghitung posisi tabel
35:
36: 0041 90 00 39 MOV DPTR,#TabelKota ; Alamat awal TebelKota
37: 0044 23 RL A ; A:=A*2
38: 0045 25 82 ADD A,DPL ; DPTR := DPTR + 2*A
39: 0047 F5 82 MOV DPL,A
40: 0049 E4 CLR A
41: 004A 35 83 ADDC A,DPH
42: 004C F5 83 MOV DPH,A
43:
44: ; ***** Mengambil alamat string
45:
46: 004E E4 CLR A
47: 004F 93 MOVC A,@A+DPTR ; ambil alamat byte kecil
48: 0050 C0 E0 PUSH A ; simpan dulu
49: 0052 A3 INC DPTR ; alamat tabel berikut
50: 0053 E4 CLR A
51: 0054 93 MOVC A,@A+DPTR ; ambil alamat byte besar
52: 0055 F5 83 MOV DPH,A ; simpan ke DPTR byte besar
53: 0057 D0 82 POP DPL ; DPTR byte kecil
54: 0059 80 07 =0062 SJMP OutString ; DPTR = alamat string
55:
56: ; ***** Mengirim string ke port seri
57:
58: 005B OutHuruf:
59: 005B 30 99 FD =005B JNB TI,$ ; sudah boleh kirim huruf?
60: 005E F5 99 MOV SBUF,A ; kirim huruf lewat port seri
61: 0060 C2 99 CLR TI ; baru saja kirim huruf
62: 0062 OutString:
63: 0062 E4 CLR A
64: 0063 93 MOVC A,@A+DPTR ; ambil 1 huruf
65: 0064 A3 INC DPTR ; alamat huruf berikutnya
66: 0065 70 F4 =005B JNZ OutHuruf ; <>00 kirim ke port seri
67: 0067 22 RET ; = 00 selesai
Sub-rutin PilihString bertugas memilih string dan kemudian mengirimkannya ke port seri agar bisa dicetak pada layar PC. Sub-rutin ini terdiri dari 3 bagian:
- Memakai A untuk mengambil salah satu alamat string yang tercatat dalam TabelKota.
Alamat awal dari TabelKota (dalam hal ini adalah 0039 seperti terlihat dalam Assembly listing) dicatat dulu pada DPTR (baris 36), setiap kota dalam TabelKota (baris 27 sampai 30) diwakili dengan alamatnya yang masing-masing 2 byte.
Nomor kota yang disimpan di A terlebih dulu dikalikan dengan 2 (baris 37), nilai ini dijumlahkan dengan nilai DPL (byte kecil dari DPTR yang kapasitasnya 2 byte) dan disimpan kembali ke DPL pada baris 38 dan 39. Meskipun dalam contoh program ini tidak akan terjadi, tapi untuk menjaga semua kemungkinan, dalam baris 40 sampai 42 diadakan juga perhitungan untuk DPH (byte besar dari DPTR), yakni untuk menjaga-jaga kalau dalam perhitungan baris 38 terjadi limpahan penjumlahan.
Sampai di sini DPTR sudah menunjuk ke alamat dari string kota yang akan dikirim ke port seri. - Mengambil alamat string dalam TabelKota yang terpilih ke DPTR.
Alamat string dalam TabelKota disimpan sebagai bilangan dua byte, jadi harus diambil dua kali tidak bisa sekali gus.
Karena TabelKota berada di dalam memori-program, maka instruksi yang dipakai adalah MOVC A,@A+DPTR (baris 47 dan 51), agar alamat memori yang diambil isinya hanya ditentukan oleh DPTR, pada baris 46 dan 50 A di-nol-kan terlebih dulu.
Baris 47 mengambil isi TabelKota byte pertama, seharusnya hasil pengambilan ini diisikan ke DPTR, tapi berhubung DPTR masih diperlukan untuk pengambilan byte berikutnya (baris 51), maka pengambilan byte pertama ini disimpan dulu ke stack (baris 48).
Untuk mengambil isi TabelKota byte kedua, nilai DPTR dinaikkan 1 (baris 49), dan hasil pengambilan byte kedua ini langsung disimpan ke DPH (baris ) karena saat ini nilai DPTR sudah boleh dirubah.
Byte pertama yang tadi disimpan ke dalam stack, dimbil kembali dari stack dan disimpan ke DPL (baris 53). Kini DPTR berisikan alamat string yang akan dikirim ke port seri. - Mengirim string yang alamatnya tercatat di DPTR ke PC lewat port seri.
Baris 59 sampai 61 dipakai untuk mengirim 1 huruf ke PC lewat port seri, sedangkan OutString pada baris 62 sampai 67 merupakan rutin yang sama yang sudah dibahas dalam Potongan Pogram 2