Bab 1 Presentasi Laporan Pendahuluan Antara Analisa Makro Ekonomi
BAB 7 MAKRO
-
Upload
eddyyudianto -
Category
Documents
-
view
723 -
download
9
Transcript of BAB 7 MAKRO
BAB II
PEMBAHASAN
2.1 Pengenalan
Makro (macro) adalah nama simbolik dari string teks atau satu blok kode yang akan
digunakan berulang-ulang dalam program. Pada turbo assembler disediakan operator makro
yang mudah dan fleksibel dengan kemampuan yang andal. Di samping itu juga terdapat
fasilitas makro beberapa (multiline macros) baris dengan argumennya.
Makro teks adalah symbol yang mewakili karakter-karakter teks. Ketika turbo
assembler menemukan symbol dalam ekspresi (atau situasi lain) maka assembler akan
menggantikan dengan karakter teks symbol tersebut. Contoh, jika DoneMsg adalah teks
makro yang mempunyai nilai “Returning to DOS” maka statemen berikut:
GoodBye DB DoneMsg
Menghasilkan
GoodBye DB ‘Returning to DOS’
EQU
Perintah EQU digunakan untuk mendefinisikan makro. Berikut ini sintaks untuk
mendefinisikan makro:
Name EQU text_string
Text_string berhubungan dengan makro teks yang bernama Name.
Text_string ditulis di dalam notasi tanda<>, contoh:
DoneMsg EQU <’Returning to DOS’>
Berikut ini kemungkinan bias terjadi kesalahan pada pendefinisian makro, contoh:
Bumi EQU tanah ; Bumi = “tanah”
Planet EQU Bumi ; Planet = “tanah” (Salah !)
Planet EQU <Bumi> ; Planet = “Bumi” (Salah !)
1
CASTER
Perintah ini mendefinisikan makro teks baru dengan menggabungkan beberapa string
secara bersamaan. CASTER mempunyai sintak sebagai berikut:
Name CASTER string[,string]…
CASTER menggabungkan string dari kiri ke kanan. Turbo assembler membuat makro teks
baru dengan nama name.
SUBSTER
Perintah ini mendefinisikan makro teks baru yang merupakan sebagian string dari
sebuah string. Sintaknya sebagai berikut:
Name SUBSTER string, position_expression[,size_expression]
Makro teks yang baru, Name terdiri dari bagian string yang dimulai dari karakter
position_expression, dengan panjang sebanyak size_expression karakter. Jika size_expression
tidak dituliskan maka secara otomatis seluruh sisa karakter dari mulai position_expression
akan dimasukkan ke dalam makro teks name. turbo assembler menganggap karakter pertama
string sebagai posisi 1.
INSTR
Perintah ini mengembalikan posisi suatu string di dalam string yang lain. Sintaknya
sebagai berikut:
Name INSTR [start_expression,]string1,string2
Turbo assembler memberikan name nilai numeric posisi string2 dalam string1. Karakter
pertama pada string1 mempunyai posisi 1. Jika string2 tidak ada dalam string1 maka nilai
posisinya 0. Jika start_expression dituliskan maka pencarian dimulai dari karakter
start_exspression tersebut dan karakter pertama string adalah 1.
SIZESTR
Perintah ini mengembalikan nilai banyaknya karakter dalam sebuah makro teks
(jumlah karakter dalam string). Sintaknya sebagai berikut:
2
Name SIZESTR string
Name diberi nilai numeric panjang dan string. String null <> mempunyai panjang nol.
Contoh manipulasi makro teks:
VERSION T300
ABC EQU <abc> ; ABC = “abc”
ABC2 EQU ABC ; ABC2= “ABC”
ABC EQU <def> ; ABC = “def” (definisi ulang)
ABC3 CATSTR ABC2,<,>,ABC,<,>,ABC2 ; ABC3= “ABC,DEF,ABC”
ABCLEN SIZESTR ABC ; ABCLEN = 3
ABC3LEN SIZESTR ABC3 ; ABC3STR = 11
COMMA1 INSTR ABC3,<,> ; COMMA1 = 4
COMMA2 INSTR COMMA1+1,ABC3,<,> ; COMMA2 = 8
ABC4 SUBSTR ABC3,5 ; ABC4 = “def,ABC”
ABC5 SUBSTR ABC3,5,3 ; ABC5 = “def”
ABC6 EQU 3+2+1 ; ABC6 = 6
ABC7 EQU %3+2+1 ; ABC7 = “6”
ABC8 EQU %COMMA1 ; ABC8 = “4”
MAKRO BANYAK BARIS
Fasilitas makro banyak baris digunakan untuk mendefinisikan batang tubuh intruksi,
perintah, atau macro lain yang disertakan ke dalam program, di mana saja ,akro tersebut di
tempatkan. Argument diberikan dalam makro dan turbo assembler akan menggantikan batang
tubuh macro dalam module jika disertakan di dalamnya.
3
Sintak untuk mendefinisikan makro banyak baris secara umum:
Name MACRO parameter_list
Macro_body
ENDM
Name adalah nama makro banyak baris yang didefinisikan. Macro_body mengandung
statemen-statemen yang membangun batang tubuh makro. Kita dapat menempatkan berbagi
statemen valid turbo assembler dalam makro. ENDM adalah kata kunci untuk menutup
makro.
Contoh berikut makro yang diberi nama PUSHALL, ketika dimasukkan ke dalam
program, maka akan disertakan semua perintah yang ada di dalamnya.
PUSHALL MACRO
PUSH AX BX CX DX
PUSH DS SI
PUSH ES DI
ENDM
Parameter_list adalah symbol argument dami (dummy) untuk macro.
Sintaknya sebagai berikut:
[argument_dami[,argument_dami…]]
Kita bisa membuat argumen dami sepanjang baris atau dengan menggunakan karakter \ dapat
meneruskan pada baris berikutnya.
Contoh:
ADDUP MACRO dest,
s1, s2
MOV dest, s1
4
ADD dest,s2
ENDM
Setiap argument dami mempunyai sintak:
Nama_dami [:tipe_dami]
Nama_dami adalah nama simbolik yang digunakan untuk tempat menyimpan
argument actual yang ditransfer ke dalam makro pada saat d panggil. Tipe_dami adalah
pilihan yang menspesifikasikan sesuatu bentuk di mana argument actual harus mengambilnya
ketika makro disisipkan.
Makro adalah nama symbol yang diberikan terhadap satu atau banyak perintah bahasa
assembly. Ketika dibuat, makro mungkin digunakan dalam program berulangkali sesuai
dengan keperluan. Keuntungan mendefinisikan makro adalah perintah ini hanya dibuat sekali:
setiap kali makro dipanggil, assembler membangkitkan perintah di dalamnya. Misalkan kita
akan menuliskan instruksi berikut untuk menampilkan isi DL berkaliikali dalam program:
Mov ah, 2
Int 21 h
Kita bisa menyimpan intruksi-intruksi tersebut dalam prosedur dan memanggilnya setiap kali
diperlukan. Namun, cara ini memerlukan intruksi tambahan yaitu CALL dan RET, yang
menyebabkan program menjadi lambat. Cara yang lebih baik adalah membuat makro,
misalnya diberi nama PUTCHAR.
Sekali PUTCHAR didefinisikan, dia dapat dipanggil dari mana saja dalam program.
Memanggil makro berbeda dengan memanggil prosedur—ini berarti perintah-perintah dalam
makro disisipkan dalam program di mana dia dipanggil. Misalkan, kita definisikan makro
bernama PUTCHAR.
Putchar macro ; mulai pendefinisian makro
mov ah, 2
int 21 h
endm ; akhir pendefinisian makro
5
Dalam segmen kode kita dapat memanggil PUTCHAR hanya menggunakan namanya. Setiap kali
makro dipanggil, assembler menyisipkan intruksi-intruksi yang ada dalam definisi makro ke dalam
kode program:
Kode Sumber Kode yang Diperluas
.code
main proc
…
…
mov dl, ‘A’
putchar
…
…
…
mov dl, ‘*’
putchar
…
…
.code
main proc
…
…
mov dl, ‘A’
mov ah, 2
int 21h
…
…
mov dl, ‘*’
mov ah, 2
int 21h
…
Perluasan tersebut dilaksanakan oleh assembler selama pembacaan pertama terhadap file
sumber dan hasilnya ditunjukkan dalam file listing (.LST).
Makro dieksekusikan lebih cepat daripada prosedur karena tidak membutuhkan intruksi
CALL dan RET sepert pada prosedur.
Melewatkan parameter. Satu fitur utama makro adalah kemampuannya untuk menangani
parameter yang dikirim. Ketika memanggil PUTCHAR, misalnya kita akan memberikan nilai
DL dengan karakter yang akan ditampilkan sebelum memanggil makro. Akan tetapi, jika kita
6
menambah parameter pada definisi makro (char), kita dapat melewatkan karakter pada baris
yang sama pada saat memanggil makro:
putchar makro char
mov ah, 2
mov dl, char
int 21h
endm
.code
…
…
putchar ‘A’
Pengiriman parameter dalam makro membuatnya lebih fleksibel dan baik serta dapat
digunakan kapan saja.
Makro untuk membuat data. Makro mungkin dipanggil dari segmen data. Misalkan, makro
dapat digunakan untuk mengalokasikan ruang untuk variable. Pada contoh berikut, setiap isi
table dibuat oleh makro ALLOC yang derifi dari empat ruang dan empat byte nol:
alloc macro varname, numbyte
varnamedb numbyte dup (‘ ’, 0, 0, 0, 0)
endm
…
…
.data
alloc value1, 20
alloc value2, 50
7
kode yang diperluas:
value1 db 20 dup(‘ ’, 0, 0, 0, 0)
value2 db 50 dup(‘ ’, 0, 0, 0, 0)
Perlu diketahui, varname dan numbytes adalah parameter yang diperoleh dari argument yang
dikirim pada saat makro dipanggil.
PENDEKLARASIAN DAN PEMANGGILAN MAKRO
Makro dapat dideklarasikan di mana saja dalam program, menggunakan perintah
MACRO dan Endm. Sintaknya sebagai berikut:
Macroname MACRO [parameter-1][, parameter-2] …
Statements
ENDM
Perintah-perintah antara MACRO dan ENDM tidak di-assemble sampai makro ditemukan.
Macroname mungkin suatu nama smbol. Parameter adalah pilihan. Mungkin terdapat lebih
dari satu perameter dalam defines makro, asalkan dipisahkan oleh koma dan ditulis pada baris
yang sama. Parameter-parameter ini sering disebut parameter dummy, mewkili nilai yang
akan dikirim ketika makro digunakan. Semua statemen sebelum ENDM dianggap sebagai
bagian dari makro.
Pemanggilan makro. Suatu makro dipanggil pada saat namanya ditemukan beserta nilai-nilai
yang akan dikirimnya. Pemanggilan makro berarti menyisipkan perintah-perintah dalam
makro langsung dalam program. Sintak pemanggilan makro:
Macroname [argument-1][, argument-2] …
Macroname harus merupakan nama makro yang telah didefinisikan sebelum dalam file
sumber. Setiap argument adalah nilai yang dilewatkan ke makro, yang akan dikembalikan
menimpa parameter dalam definisi makro asal. Urutan argument harus sesuai dengan
parameter asa, tetapi jumlah parameter tidak boleh lebih banyak dari jumlah parameter asli.
Jika terlalu banyak maka parameter selebihnya akan diabaikan. Jika parameternya kurang
maka nilai parameter sisanya akan diset dengan string null:
8
Contoh: makro DISPLAY. Untuk mengetahui bagaimana semua ini bekerja, kita buat sebuah
makro yang diberi nama DISPLAY yang menampilkan string yang ditunjuk oleh DX. Tidak
ada parameter yang dispesifikasikan oleh makro.
display macro
push ax
mov ah, 9
int 21h
pop ax
endm
seperti dalam prosedur, kita sering push dan pop register dalam makro dengan tujuan untuk
menjaga nilainya. Berikut ini untuk memanggil makro tersebut:
mov dx, offset message
display
…
PENGIRIMAN PARAMETER
Penggunaan parameter dalam definisi makro membuatnya lebih fleksibel. Kita tulis kembali
makro DISPLAY menggunakan parameter yang disebut string, yaitu nama string yang akan
ditampilkan:
display macro string
push ax
push dx
mov ah, 9
mov dx, offset string
int 21h
pop dx
9
pop ax
endm
Jadi, parameter string ditimpa setiap kali makro dipanggi. Jika kita ingin menampilkan tiga
string, kita dapat memanggil makro tiga kali, mengirim argument yang berbeda tiap kali:
display msg1
display msg2
display msg3
…
…
…
msg1 db ‘ini pesan pertama’
msg2 db ‘ini pesan kedua’
msg3 db ‘ini pesan ketiga’
Nama yang digunakan parameter dummy tidakakan tampil dalam listing program.
Pengiriman argument membuat makro DISPLAY berguna. Kita dapat menghindari
komplikasi umum yang terlibat dalam pengiriman parameterke prosedur. Kode berikut
menunjukkan kode yang dibangkitkan oleh assembler. Kita harus membayar harga
kemudahan makro dengan ukuran program yang besar:
Display msg1
push ax
push dx
mov ah, 9
movdx, offset msg1
int 21h
10
pop dx
pop ax
display msg2
push ax
push dx
mov ah, 9
mov dx, offset msg2
int 21h
pop dx
pop ax
display msg3
push ax
push dx
mov ah, 9
mov dx, offset msg3
int 21h
pop dx
pop ax
Makro LOCATE. Makro LOCATE meletakkan kursor pada kolom dan baris yang diinginkan
dalam layer:
locate macro row, column
push ax
push bx
11
push dx
mov bx, 0
mov ah, 2
mov dh, row
mov dl, column
int 10h
pop dx
pop bx
pop ax
endm
LOCATE mungkin dipanggil dengan mengirimkan nilai immediate, operand memori, atau
nilai register selama panjangnya 8 bit:
locate 10, 20
locate row, col
locate ch, cl
Hati-hati dalam mengirim register sebagai argument karena mungkin terjadi konflik dengan
register yang sama yang digunakan dalam makro.
Makro STARTUP. Makro STARTUP menginisialisasi register DS dan ES ke lokasi segmen
data dan menyimpan alamat segmen PSP dalam variable. STARTUP dirancang untuk bekerja
dengan perintah segmen sederhana:
startup macro pspseg
push ds
mov ax, @data
mov x, ax
12
move s, ax
pop pspseg
endm
contoh pemanggilan
startup myPSP
MAKRO BERSARANG
Salah satu cara untuk menyederhanakan makro adalah menggunakan makro yang sudah ada.
Makro bersarang akan memanggil makro lain. Misalkan dibuat makro yang disebut
DISPLAY_AT yang menampilkan string pada baris dan kolom yang diminta. Makro ini
memanggil makro LOCATE dan DISPLAY dengan mengambil parameter yang dimilikinya
dan mengirimnya sebagai argument ke makro lain:
display_at macro row, col, string
locate row, col
display string
endm
contoh pemanggilan
display_at 10, 15, greeting
…
greeting db ‘Hello dari baris 10, kolom 15’
PERINTAH LOCAL
Perintah LOCAL memaksa assembler untuk membuat nama unik untuk label setiap makro
dipanggil. Sintaknya sebagai berikut:
LOCAL labelname
13
Makro mungkin memerlukan label sebagai titik acuan untuk intruksi loncat (jump) atau loop.
Kita buat makro yang diberi nama REPEAT yang menampilkan karakter yang diminta
berulang kali.
Perintah LOCAL menyuruh assembler untuk mengubah L1 menjdi nama yang unik setiap kali
makro dipanggil:
repeat macro char, count
local L1
mov cx, count
L1 : mov ah, 2
mov dl, char
int 21h
loop L1
endm
Jika kita memanggil REPEAT lebih dari sekali, kita akan melihat bagaimana assembler
membuat label yang berbeda setiap kali. Assembler member nomor label dari 0000h sampai
FFFFh dan mendahuluinya dengan tanda Tanya.
repeat ‘A’, 10
mov cx, 10
??0000 : mov ah, 2
mov dl, ‘A’
int 21h
loop ??0000
repeat ‘*’, 20
movcx, 20
14
??0001 : mov ah, 2
Mov dl, ‘*’
Int 21h
Loop ??0001
2.2 TEKNIK KHUSUS
PROSEDUR PEMANGGILAN MACRO
Salah satu kekurangan yang dimiliki pengguna makro adalah makro meningkatkan jumlah
kode yang dibangkitkan oleh assembler karena setiap makro yang dipanggil merupakan
salinan dari seluruh perintah dalam makro tersebut. Dari sisi ukuran program, prosedur lebih
ekonomis.
Kompromi terbaik antara keduanya adalah mempersingkat pengiriman parameter untuk
pemanggilan prosedur. Menggunakan prosedur jika intruksi yang sama harus digunakan lebih
dari sekali. Makro dapat menempatkan setiap parameter yang dikirim ke dalam register yang
benar dan kemudian memanggil prosedur. Kita gunakan teknik ini untuk memanggil prosedur
WRITEINT, yang akan menampilkan integer tidak bertanda pada konsol.
Pemanggilan prosedur WRITEINT. Makro CALL_WRITEINT memanggil prosedur
WRITEINT dari CONSOLE.LIB. Dua parameter , value dan radix, di-load ke dalam AX dan
BX. Kita menyimpan dan mengambil kembali kedua register sebelum dan sesudah
pemanggilan prosedur untuk meminimalkan dampaknya pada keseluruhan program:
call_writeint macro value, radix
push ax
push bx
mav ax, value
mov bx, radix
call writeint
pop bx
15
pop ax
endm
Kita dapat memanggil makro menggunakan register, variabel atau konstanta yang membuat
prosedur lebih fleksibel. Tiga nilai ditampilkan oleh WRITEINT dalam contoh berikut adalah
8192, 1234, dan 1000000000000:
mov dx, 1234
call_writeint 2000h, 10
call_writeint dx, 16
call_writeint wordval, 2
…
…
Worldval dw 1000h
PERINTAH ASSEMBLY-KONDISIONAL
Dua belas perintah assembly-kondisioanal yang berbeda dapat digunakan bersamaan dengan
makro untuk membuatnya lebih andal. Sintaak umum perintah assembly-kondisional adalah:
IF condition
Statement
[ELSE
Statement]
ENDIF
Beberapa perintah kondisi berikut akan diproses dalam perintah di atas:
IF Sintak IF ekspresi
Mengizinkan assembly jika nilai ekspresi benar (tidak nol). Contoh berikut
mengizinkan assembly jika count kurang dari 20:
16
IF count LT 20
Operator berkaitan yang mungkin: LT, GT, EQ, NE, LE dan GE
IFE Sintak IFE ekspresi
Mengizinkan assembly jika nilai ekspresi salah satu nol. Contoh berikut mengizinkan
assembly jika count = 10:
IFE (count-10)
IF1 Sintak IF1
Mengizinkan assembly jika nilai sekarang merupakan nilai pertama dari file sumber
(hanya Microsof Assembly).
IF2 Sintak IF2
Mengizinkan assembly jika nilai sekarang merupakan nilai kedua dari file sumber
(hanya Microsof Assembly).
IFB Sintak IFB <argumen>
Mengizinkan assembly jika argument kosong. Nama argument harus berada dalam
kurung siku.
IFNB Sintak IFNB <argumen>
Mengizinkan assembly jika argumen tidak kosong.
IFIDN Sintak IFIDN <argumen1>,<argumen2>
Mengizinkan assembly jika kedua argument identik. Jika menggunakan perintah
IFIDNI maka perbandingannya case sensitive.
IFDIF Sintak IFDIF <argumen1>,<argumen2>
Mengizinkan assembly jika kedua argument tdak identik. Jika menggunakan perintah
IFDIFI maka perbandingannya case sensitive.
IFDEF Sintak IFNDEF name
Mengizinkan assembly jika name telah didefinisikan.
17
IFNDEF Sintak IFNDEF name
Mengizinkan assembly jika name belum didefinisikan.
ENDIF akhir blok yang dimulai dengan menggunakan perintah kondisional.
ELSE mengassembly semua perintah sebelum ENDIF jika kondisi yang diperoleh pada
kondisi IF bernilai salah.
Pemeriksaan Argumen Makro. Makro mungkin mempunyai satu atau lebih parameter pilihan.
Ini harus memeriksa untuk melihat apakah setiap argument benar-benar dikirim. Jika tidak,
assembly mengembalikan nilai blank untuk parameter dalam makro. Misalkan kita
memanggil makro CALL_WRITEINT, tanpa mengirim nilai radix. Pada baris lima akan
disassembly dengan intruksi yang salah:
Pemanggilan MACRO : call_writeint 1000h
Perintah perintah yang dibangkitkan
1 : call_writeint
2 : push ax
3 : push bx
4 : mov ax, 1000h ; nilai yang akan ditampilakn
5 : mov bx, ; radik yang digunakan (?)
6 : call writeint ; menampilkan AX dalam konsol
7 : pop bx
8 : pop ax
Perintah IFB akan mengembalikan nilai benar jika argument makro kosong, dan IFNB
mengembalikan nilai benar jika argument makro ada isinya.
Contoh, makro berikut, yang diberi nama MYMAC, memeriksa nilai parml apakan nilainya
ada pada saat dipanggil. Jika MYMAC dipanggil tanpa argumen, perintah EXITM akan
mencegah program lainnya untuk dibangkitkan:
18
mymac macro parml
ifb <parml>
exitm
endif
….
….
.code
mymac
mymac vall
PERINTAH EXITM
Perintah EXITM memerintahkan assembler untuk keluar dari makro dan menghentikan
pembangkitan kode. Ini mengurangi jumlah kode pada program akhir. Jika tidak diperlukan,
intruksi dapat dihilangkan.
Mislkan kita buat makro yang disebut GOTOXY yang memprosisikan kursor pada layar pada
posisi yang diberikan X, Y. kita ingin kelur dari makro jika kedua argument kurang dari nol.
Kondisi IF membandingkan xval dengan nol menggunakan LT dan keluar jika nilainya benar.
Begitu juga untuk xval:
gotoCY macro xval, yval
if xval LT 0
exitm
endif
if yval LT 0
exitm
endif
mov bx, 0
19
mov ah, 2
mov dh, yval
mov dl, xval
int 10h
endm
Perintah kondisi seperti IF harus diikuti oleh ekspresi yang dapat dievaluasi nilai benar atau
salahnya pada saat assembly. Hal ini tidak akan bekerja pada nilai dalam register atau variabel
memori.
Menampilkan pesan selama assembly. Perintah %OUT digunakan untuk menampilkan pesan
selama assembly untuk menunjukkan progress, sebagai berikut:
gotoCY macro xval, yval
if xval LT 0
%out Argumen (xval) yang dikirim ke GOTOXY tidak benar.
%out (nilai harus >= 0)
endif
if yval LT 0
%out Argumen (yval) yang dikirim ke GOTOXY tidak benar.
%out (nilai harus >= 0)
endif
mov bx, 0
mov ah, 2
mov dh, yval
mov dl, xval
int 10h
20
endm
Jika kita memanggil GOTOXY dengan argument -1 dan -2 maka akan ditampilkan pesan
berikut:
Argumen (-1) yang dikirim ke GOTOXY tidak benar.
(Nilai harus >= 0)
Argumen (-2) yang dikirim ke GOTOXY tidak benar.
(Nilai harus >=0)
Makro WRITE. Berikut ini makro yang disebut WRITE yang menulis huruf ke output standar.
Huruf dikirim sebagai argument tunggal:
write macro text, creturn
local string, crlf
push ax
push dx
mov ah, 9
mov dx, offset string
int 21h
ifnb <creturn>
mov dx, offset crlf
int 21h
endif
pop dx
pop ax
.data
21
string db text, ‘$’
crlf db 0Dh, 0Ah, ‘$’
.code
endm
Perintah DATA ditulis sebelum definisi variabel, ini diperlukan ketika menggunakan perintah
segmen sederhana karena assembler selalu menghitung offset variabel dari segmen data.
Perintah LOCAL digunakan dengan string dan crlf pada awal makro, sehingga nama ganda
tidak akan dibuat ketika makro dipanggil lebih dari satu kali.
Makro WRITE baik khususnya untuk menampilkan pesan pada konsol karena membuat
program sumber mudah untuk dibaca. Berikut ini contoh pemanggilan makro WRITE:
Write ‘Hello there’, N
Write ‘No return on this line’
2.3 OPERATOR MAKRO
Terdapat lima operator makro yang membuat makro lebih fleksibel ketika dipanggil.
Berikut ini kelima operator tersebut:
& operator substitusi
<> operator teks-harfiah
! operator karakter-harfiah
% operator ekspresi
;; komentar makro
Operator substitusi (&). Dengan operator &, kita dapat mengganti parameter dengan nilai
yang telah dikirim sebagai argumen. Sintaknya:
¶meter
Operator ini berguna khususnya ketika teks yang dikirim sebagai argument harus disisipkan
ke dalam string atau instruksi dalam makro. Contoh, makro DOSmsg brikut untuk membuat
ruang memori untuk string yang dikirim sebagai argumen:
22
DOSmsg macro num, string
msg&num db ‘DOS error : &String’, 0
endm
Tabel berikut menunjukkan contoh pemanggil DOSmsg beserta hasilnya:
Dipanggil Kode yang Diperluas
DOSmsg 1, <Invalid function>
DOSmsg 2, <File not found>
DOSmsg 3, < Path not found>
msg1 db ‘DOS Error : Invalid function’,0
msg2 db ‘DOS Error : File not found’,0
msg3 db ‘DOS Error : Path not found’,0
Operator Ekspresi (%). Kadang-kadang hasil ekspresi harus dikirim sebagai argument makro.
Operator % digunakan pada awal ekspresi untuk memberitahu assembler bahwa hasil
ekspresinya, bukan ekspresinya sendiri, dikirim ke makro.
Berikut ini makro MEMDISPLAY yang menulis string langsung ke buffer video. Kita dapat
memanggil makro baik menggunkan nilai angka tunggal atau ekspresi:
memdisplay macro offset, string
mov ax, videoseg
mov es, ax
mov di, offset
…
…
…
endm
ketika pemanggilan MEMDISPLAY, argument pertama adalah offset ke dalam buffer video
untuk karakter pertama yang akan ditampilkan. Argumen kedua adalah nama string. Offset
23
dapat berupa nilai tunggal seperti 320, atau dapat berupa hasil ekspresi yang melibatkan
simbol konstanta:
row = 10
col = 40
…
memdisplay %((row * 160)+(col*2)), string1
memdisplay 320, string2
Operator teks-harfiah (<>). Operator teks-harfiah mengelompokkan serangkaian karakter ke
dalam sebuah string. Ini menghindari kesalahan assembler dari interpretasi bahwa isi
rangkaian tersebut merupakan argument terpisah. Berikut ini contoh makro MESSAGE.
Message macro text
db ‘&text’, 0
endm
Pemanggilan makro berikut:
message<Efficiensy is 50 %, & falling;>
akan di-assembly sebagai berikut:
db ‘Efficiensy is 50 %, & falling;’,0
Operator karakter-harfiah (!). Operator karakter-harfiah ditemukan dengan tujuan yang sama
seperti operator teks-harfiah. Operator ini memaksa assembler untuk memperlakukan karakter
khusus. Berikut ini contoh penggunaannya :
message<Efficiensy is !> than 50%>
ini akan di-assembly sebagai:
db ‘Efficiensy is> than 50%’, 0
24
2.4 LIBRARY MAKRO
Makro CCALL. Salah satu penggunaan makro yang sangat baik adalah meningkatkan set
intsruksi Intel—ini akan memudahkan program untuk ditulis. Makro CCALL (condition call)
memungkinkan untuk memanggil prosedur berdasarkan flag, menggunakan instruksi tunggal:
Ccall macro con, procname
local L1, L2
j&cond L1
jmp L2
L1 : call procname
L2 : exitm
endm
Makro dapat berdasarkan kondisi flag tertentu. Contoh, kita dapat memanggil prosedur
DOS_ERROR ketika CF diset. Misalkan sebagai berikut:
Ccall c, DOS_error
Atau, kita memanggil LOWER jika value 1 kurang dari atau sama dengan AX:
Asal Kode yang dibangkitkan
cmp value 1, ax cmp value1, ax
Ccall le, lower jle ??0002
jmp ??0003
??0002 : call lower
??0003 :
Kita dapat memanggil NOT_EQUAL jika AX tidak sama dengan BX :
cmp ax, bx
Ccall ne, not_equal
25
Setelah membandingkan dua string, kita dapat memanggil EXCHANGE :
call compare
Ccall a, exchange
Makro CMPJ. Makro CMPJ (compare and jump) membandingkan dua operand dan loncat ke
kabel berdasarkan flag:
cmpj macro dest, flag, source, label
cmp dest, source
j&flag label
endm
Contoh Pemanggilan
cmpj ax, le, bx, labell ; jika AX <= BX, loncat ke labell
cmpj cx, e, count, exit ; jika CX = count, loncat ke exit
Makro MULT. Seperti kita ketahui, instruksi MUL menyebabkan keterbatasan tertentu; AL
atau AX merupakan operand tujuan otomatis, dan operand sumber immediate tidak
diperbolehkan. Makro MULT pada contoh berikut melalkukan perkalian operand 16-bit oleh
register, operand memori, atau operand immediate:
mult macro dest, source
push ax
push bx
mov ax, dest
mov bx, source
mul bx
mov dest, ax
pop bx
26
pop ax
endm
Makro MULT mengalikan dest dengan source, menempatkan hasilnya dalam dest. Jika
hasilnya lebih besar dari 16 bit, maka CF diset dan bagian atas hasinya disimpan dalam DX.
Contoh berikut memenggil MULT mendemontrasikan fleksibilitas dalam perkalian operand
berbagai tipe:
mov cx, value 1
mult cx, 5
mult value1, value2
mult value2, 5
…
…
value 1 dw 100h
value2 dw 2
Makro MMOVE. Set intruksi Intel tidak mempunyai instruksi pemindahan dari memor ke
memori. Makro MMOVE dapat melakukan hal ini, seperti contoh berikut:
mmove macro dest, source
push ax
if (type dest) EQ 1
mov a1, source
mov dest, al
else
if (type dest) EQ 2
mov ax, source
27
mov dest, ax
endif
endif
pop ax
endm
Contoh Pemanggilan
mmove word2, word1 ; 16-bit move
mmove byte2, byte1 ; 8-bit move
Oleh karena operator TYPE digunakan pada makro ini maka pesan kesalahan akan
ditampilkan jika tdak terdapat perintah. DATA pada file sumber sebelum definisi makro. Hal
ini terjadi karena assembler memerlukan untuk meletakkan variable sebelum dapat
mengevaluasi tipenya. Segmen berikut mungkin bisa digunakan:
.stack 100h
.data
(variabel)
(definisi makro)
.code
(intruksi)
Loncat Kondisioanal dan Liupan (Conditional Jumps and Loops). Set instruksi Intel
mempunyai batasan jangkauan instruksi loncat kondisional—termasuk LOOP—sampai 127
ke depan atau 128 byte ke belakang. Khususnya, ketika program mempunyai sejumlah
pemanggilan makro dalam jangkauan loncat kondisional atau liupan, ini mungkin
menyebabkan keluar dari range. Misalkan, kita akan mengonversi prosedur WRITESTRNG,
READSTRING dan WRITEIN menjadi makro dan menggunakannya dalam program:
Mov cx, 10
L1 : writestring promt
28
readstring buffer
writein 1000h, 10
loop L1
Contoh ini akan menyebabkan kesalahan sintak karena kode menghasilkan dengan makro di
dalamnya, liupan yang lebih dari 127 byte sehingga LOOP akan keluar range.
Makro LLOOP. Makro LLOOP (long loop) mengizinkan kita untuk meliup ke suatu label
dalam segment sekarang. Dia melakukan in dengan meliup ke instruksi JMP yang meloncat
ke tujuan. JMP, tidak seperti LOOP, dapat menjangkau suatu label dalam segmen:
LLoop macro dest
local A1, A2
loop A1
jmp A2
A1 : jmp dest
A2 :
endm
Makro menggunakan instruksi LOOP tidak seperti biasanya. Dia meloncat ke depan kelabel
A1. Pada lokasi ini, instruksi JMP kembali loncat ke dest. Ketika CX = 0, LOOP terjadi dan
loncat ke A2, yaitu lokasi instruksi berikutnya.
2.5 PENGGUNAN MAKRO LEBIH LANJUT
Pendefinisian Blok Berulang
Satu atau lebih perintah dapat diulang menggunakan perintah REPT, IRP dan IRPC. Hal ini
memungkinkan bagi sebuah makro untuk membuat struktur data yang besar.
Perintah REPT. Perintah REPT mengulang stu blok instruksi berdasarkan pencacah.
Sintaknya sebagai berikut:
29
REPT ekspresi
Statemen
ENDM
Ekspresi menentukan jumlah pengulangan dan mengevaluasi bilangan tidak bertanda 16-bit.
Misalkan, kita ingin menggunakan REPT untuk mendefinisikan ruang untuk table yang
mengandung data 100 mahasiswa:
index label byte
rept 100
db ? dup (?)
db 20 dup (?)
dw ?
endm
kita bisa menggunakan cara yang sama untuk makro yang dapat menggeser operand ke kiri
dengan jumlah tertentu. Contoh berikut, count menentukan jumlah instruksi SHL yang
dibangkitkan oleh assembler:
mshl macro dest, count
rept count
shl dest, 1
endm
endm
Ini merupakan definisi makr bersarang. Kita dapat melihat bagaimana makro ini dipanggil
dengan dua cara, seperti berikut ini:
mshl ax, 1
mshl bx, 4
kode yang diperluas
30
shl ax, 1
shl bx, 1
shl bx, 1
shl bx, 1
shl bx, 1
Perintah IRP. Perintah IRP membuat pengulangan blok jika setiap pengulangan mengandung
nilai yang berbeda. Sintaknya sebagai berikut:
IRP parameter, <argument [,argument] …>
Statemen
ENDM
Blok diulang sekali untuk setiap argument. Begitu mengulang, nilai argument sekarang
digantikan untuk parameter. Perintah ini berguna untuk menginisialisasi table atau blok data
dimana terdapat nilainya yang bervariasi. Argument mungkin berupa nama symbol, string
atau konstanta numeric.
Statemen sumber
irp parm, <10, 20, 30, 40>
dw parm, parm*2, parm*3, parm*4
endm
Dibangkitkan oleh assembler
dw 10, 10*2, 10*3, 10*4
dw 20, 20*2, 20*3, 20*4
dw 30, 30*2, 30*3, 30*4
dw 40, 40*2, 40*3, 40*4
IRP dapat menginialisai table offset prosedur. Ini membuktikan kegunaan jika kita ingin
mengkodekan pencabangan dengan berbagai cara berdasarkan nilai index. Contoh:
31
mov bx, indexvalue ; memilih table entry
call proctable [bx] ; pemanggilan tidak langsung
Empat nama prosedur dikirim sebagai argument dalam contoh IRP berikut. Masing-masing
disisipkan ketika procname tampil, menghasilkan dalam table yang mengandung offset
prosedur:
proctable label word
irp procname, <movup, movlft, movrt>
dw procname
endm
perintah-perintah berikut akan dibangkitkan:
proctable label word
dw movup
dw movdn
dw movlft
dw movrt
Makro Jump Tambahan. Program yang menggunakan loncat kondisional atau loop
memungkinkan masuk dalam masalah ketika keluar dari range yaitu 127 byte. Seperti dalam
makro LLOOP yang telah dibuat, kta dapat membuat makro extended jump yang mengizinkan
loncatkondisional ke label terdekat, sebagai berikut:
jxe macro dest
local L1, L2
je L1
jmp short L2
L1 : jmp dest
L2 :
32
endm
Dengan makro ini, kita dapat membuat instruksi sebagai berikut, dimana loopTop dapat
berada di mana saja dalam program.
jxe loopTop
Masalahnya di sini kita harus membuat makro yang terpisah untuk masing-masing instruksi
jump yang berbeda. Di sinilah kelebihan instruksi IRP yang hanya perlu satu blok instruksi
saja untuk mengakomodasi seluruh kondisi jump, sebagai berikut:
irp cond, <a, ae, b, be, e, ne, z, nz, g, ge, l, le, c, nc, o, no, p, np, s, ns>
jxe&cond macro dest
local L1, L2
j&cond L1
jmp short L2
L1 : jmp dest
L2 :
endm
endm
Berikut ini contoh pemanggilan yang dapat dilakukan:
jxa L1 ; jump extended if above
jxae L3 ; jump extended if above or equal
jxz L1 ; jump extended if zero
jxne L4 ; jump extended if not equal
jxg L2 ; jump extended if greater
jxo L1 ; jump extended on overflow
33
Makro Penggeseran Generik. Di atas telah dibuat makro MSHL yang dapat melakukan
penggeseran operand ke kiri sejumlah yang kita inginkan. Dengan mengombinasikan perintah
IRP dan makro tersebut, kita dapat membuat suatu prosedur penggeseran yang lebih andal,
sebagai berikut:
irp styp, <shl, shr, sal, sar, rol, ror, rcl, rcr>
m&styp macro dest, count
rept count
&styp dest, 1
endm
endm
endm
Contoh pemanggilan makro tersebut adalah :
mshl ax, 3
mrcl count, 2
mshr bx, 4
mror ax, 5
Instruksi yang dibangkitkan oleh assembler adalah sebagai berikut:
mshl ax, 3
shl ax, 1
slh ax, 1
slh ax, 1
mrcl count, 2
rcl count, 1
rcl count, 1
34
Perintah IRPC. Perintah IRPC pada dasarnya sama dengan IRP, kecuali jumlah karakter
dalam string argument menentukan jumlah pengulangan.
Sintaknya sebagai berikut:
IRPC parameter, string
Statement
ENDM
String harus ditutup dengan kurung siku (<>) jika mengandung spasi, atau karakter khusus
lainnya. Contoh berikut membangkitkan lima variable (value_A, value_B dan sebagainya)
menggunakan karakter dalam string ABCD sebagai argument:
irpc parm, ABCDE
value_&parm db ‘&parm’
endm
Menghasilkan perintah sebagai berikut:
value_A db ‘A’
value_B db ‘B’
value_C db ‘C’
value_D db ‘D’
value_E db ‘E’
TIP-TIP TAMBAHAN
Menyimpan Makro dalam File Include. Setelah membuat kumpulan makro, akan menjadi
tidak baik kalau harus menyalin semuanya pada setiap program baru. Terdapat cara lebih
baik, dengan membuat file yang berisi makro dan dengan menggunakan perintah INCLUDE
untuk menyalinnya pada waktu assembly. Hanya makro yang digunakan yang menjadi bagan
dari program akhir. Jika kita menggunakan two-pass assembler seperti Microsof Assembler,
35
akan lebih baik untuk menyimpan perintah INCLUDE dalam lingkungan pengecekan kondisi
IF1, yang memerintah assembler untuk melibatkan makro hanya pada saat pertama kali:
if1
include lib1.mac
endift
Berikut contoh file makro yang dapat digunakan pada aplikasi yang memerlukan salah satu
makro yang ada didalamnya:
; Macro.Inc
; File ini harus di-include pada setiap program sumber yang memerlukan. Program
juga harus di-link ke CONSOLE.LIB
call_WritInt locate
cCall mDisplay
cmpj mMove
display_at mshl
exit mult
getYN putchar
inputInt repeat
inputStr startup
jx_ write
1Loop
Extern ReadInt : proc, ReadString : proc
; menulis integer ke konsol
36
call_WriteInt macro value, radix
push ax
push bx
mov ax, value
mov bx, value
call writeint
pop bx
pop ax
endm
; pemanggilan prosedur kondisional
cCall macro cond, procname
local L1, L2
j&cond L1
jmp L2
L1 : call procname
L2 : exitm
endm
; membandingkan dua operand dan loncat ke <dest>
; berdasarkan flag
cmpj macro dest, flag, source, label
cmp dest, source
37
j&flag label
endm
; menampilkan string pada baris, kolom dalam konsol
display_at macro row, col, string
locate row, col
mDisplay string
endm
; keluar ke Dos dan mengembalikan kode
exitm macro ecode
mov ah, 4Ch
mov al, ecode
int 21h
endm
; mengambil respons Y/N (y/n). Argument <exact> harus huruf kapital yang akan
menset ZF
GetYN macro prompt, exact
write prompt
mov ah, 1
int 21h
sub al, 32
cmp al, exact
38
endm
; menampilkan prompt huruf pada <row>, <col> dan meng-input integer dan
menyimpannya pada <dest>
inputInt macro row, col, prompt, dest
locate row, col
write prompt
call ReadInt
mov dest, ax
endm
; menampilkan prompt huruf pada <row>, <col>. Kemudian, memasukkan string
ASCIIZ dan menyimpannya ke <dest>. Maksimum karakter = <max>
inputStr macro row, col, prompt, dest, max
locate row, col
write prompt
push cx
push dx
mov dx, pffset dest
mov cx, max
call ReadString
pop dx
pop cx
endm
39
; jump eXtented (JX_) ; loncat kondisional ke label NEAR (di mana saja dalam
segmen)
irp cond, <a, ae, be, e, ne, z, nz, g, ge, l, le,c, nc, o, no, p, np, s, ns>
jxe&cond macro dest
local L1, L2
j&cond L1
jmp short L2
L1 : jmp dest
L2 :
endm
endm
; Loop ke label NEAR (dimana saja dalam segmen)
1Loop macro dest
local A1, A2
loop A1
jmp A2
A1 : jmp dest
A2 :
endm
40
; meletakkan kursor pada <row>, <column> pada video halaman 0.
locate macro ro, column
push ax
push bx
push dx
mov bx, 0
mov ah, 2
mov dh, row
mov dl, column
int 10h
pop dx
pop bx
pop ax
endm
; menampilkan $-terminated string
mDisplay macro string
push ax
push dx
push ah, 9
mov dx, offset string
int 21h
41
pop dx
endm
; memindahkan word atau byte dari memori ke memori
mmove macro dest, source
push ax
if (type dest) EQ 1
mov al, source
mov dest, al
else
if (type dest) EQ 2
mov ax, source
mov dest, ax
endif
endif
pop ax
endm
; menggeser <dest> ke kiri, <count> kali dengan melakukan instruksi penggeseran
tunggal
mshl macro dest, count
rept count
shl dest, 1
42
endm
endm
; mengalikan dua operand
mult macro dest, source
push ax
push bx
mov ax, dest
mov bx, source
mul bx
mov dest, ax
pop bx
pop ax
endm
; mengeluluarkan karakter ke konsol
putchar macro char
mov ah, 2
mov dl, char
int 21h
endm
; mengeluarkan karakter <count> kali
repeat macro char, count
local L1
mov cx, count
43
L1 : mov ah, 2
mov dl, char
int 21h
loop L1
endm
; set DS dan ES ke segmen data. Menyimpan alamat segmen PSP dalam variable
startup macro pspSeg
push ds
mov ax, @data
mov ds, ax
mov es, ax
pop pspSeg
endm
; makro WRITE menulis huruf ke output standar. <text> adalah string yang berada
antara tanda kutip. Jika tidak kosong, <creturn> mengindikasikan bahwa carriage
return ditampilkan.
write macro text, creturn
local string, crlf
push ax
push dx
mov ah, 9
int 21h
44
infb <creturn>
mov dx, offset crlf
int 21h
endif
pop dx
pop ax
.data
string db text, ‘$’
crlf db 0Dh, 0Ah, ‘$’
.code
endm
; makro berikut menghasilkan delapan makro, yang bernama MSHL, MSHR, MSAR,
MROL, MROR, MRCL, dan MRCR.
irp styp, <shl, shr, sal, sar, rol, ror, rcl, rcr>
m&styp macro dest, count
rept count
&styp dest, 1
endm
endm
endm
45
2.6 OPERATOR DAN PERINTAH LANJUT
OPERATOR TIPE
Semua operator assembler berikut adalah tipe atau atribut suatu variable atau label. Operator operator tersebut adalah sebagai berikut:
TABEL 7.1 Operator assembler
Sintak Nilai yang dikembalikan
HIGH ekspresi Byte bagian atas sebuah ekspresi
LENGTH variable Jumlah elemen dalam sebuah variable
LOW ekspresi Byte bagian bawah sebuah ekspresi
OFFSET ekspresi Alamat offset sebuah ekspresi
type PTR ekspresi Memaksa ekspresi menjadi tipe yang diinginkan
SEG ekspresi Alamat Segmen sebuah ekspresi
SHORT label Set label bertipe SHORT
SIZE variable Panjang variable kali tipenya
THIS type Membuat operand tipe yang diinginkan pada lokasi sekarang
TYPE ekpresi Mode dan lingkup ekspresi
TYPE ekspresi Jumlah byte dalam variable/struktur
Operator SEG. Operator SEG mengembalikan alamat segmen sebuah label , variable, nama segmen, nama grup atau operand memori lain. Contoh berikut memindahkan segmen array ke dalam AX kemudian menyalinnya ke dalam DS:
Mov ax, seg array
Mov ds, ax
Operator SHORT. Operator ini deringkali digunakan dengan intruksi JMP ketika kita ketahui loncat ke depan akan kurang dari atau sama dengan 127 byte dari lokasi sekarang. Ini mengizinkan assembler untuk membangkitkan 2-type intruksi jump pendek daripada 3-byte intruksi jump near.
Operator TYPE. Operator type mengembalikan ukuran, dalam byte, elemen tunggal sebuah variable. Contoh: Variabel 8-bit akan mengembalikan tipe 1, variable 32-bit akan
46
mengembalikan 4, array byte akan mengembalikan 1 dan array 16-bit integer akan mengembalikan 2. Tipe label near adalah FFFFh, dan tipe label far adalah FFFEh. Contoh:
var1 db 20h
var dw 1000h
var3 dd ?
var4 db 10, 20, 30, 40, 50
msg db ‘File not found’, O
…
L1: mov ax, type var1
mov ax, type var2
mov ax, type var3
mov ax, type var4
mov ax, type msg
mov ax, type L1
Operator LENGTH. Operator Length menghitung jumlah elemen individual dalam variable yang telah didefinisikan menggunakan DUP. Jika DUP tidak digunakan , length akan mengembalikan nilai 1. Contoh:
val1 dw 1000h
val2 db 10, 20, 30
array dw 32 dup(0)
array2 dw 5 dup(3dup(0))
meddage db ‘File not found’,0
…
mov ax, length val1
mov ax, length val2
mov ax, length array
mov ax, length array2
mov ax, length message
47
Variabel string mengembalikan nilai 1. Jika operator DUP bersarang digunakan dengan nilai tipenya. Contoh, array berikut nilai 16-bit mempunyai TYPE 2 dan LENGTH 32. Dengan demikian , SIZE nya adalah 64:
intArray dw 32 dup(0)
String berikut mempunyai SIZE I karena LENGTH dan TYPE-nya sama-sama satu:
Message db ‘This is a message’,0
PERINTAH STRUC
Perintah STRUC mendefinisikan struktur (template atau pola) yang mungkin membebani ruang memori. Struktur juga dapat menganalisasi area dalam program ke nilai default. Bagian individu struktur disebut field.
Kita mendefinisikan struktur banyak persamaaannya dengan makro. Contoh, kita dapat mendefinisikan struktur menjelaskan field dari record mahasiswa. Definisi struktur berikut harus ditempatkan dalam file sumber di mana saja di depan segmen data:
StudentStruc struc ; awal struktur
stnumber db ‘0000000’
lastname db ‘ ‘ ; 20 spasi
credit dw 0
status dw 0
StudentStruc ends ; akhir struktur
Field dalam struktur berjumlah sampai 30 byte. Dalam segmen data kita dapat mendefinisikan variable struktur, dengan alokasi 30 byte memori.
.data
Srec StudentStruc <>
Tanda kurung siku (<>) diperlukan untuk memerintahkan assembler menjaga nilai field default yang disediakan dalam definisi struktur,
Penggantian nilai default. Kita dapat mengganti nilai default dengan nilai baru. Nilai baru harus dipisah dengan koma. Contoh berikut pelimpahan berbagai field dalam StudentStruc:
srec StudentStruc<’1234567’,’Dedi’,30,1> ; seluruh field
48
myRecord StudentStruc<,,50,0> ; 2 field terakhir
yourRecord StudentStruc<,’Dodi’> ; field ke 2
Field yang menggunakan operator DUP dalam deklarasi struktur asal tidak dapat dikesampingkan. Misalnya field last =name dalam deklarasi StudentStruc adalah:
Lastname db 20 dup (‘ ‘)
Usaha berikut yang mencoba menggantifield ini akan menimbulkan kesalahan sintak:
Srec StudentStruc <,’Joni’>
MenggunakanVariabel Struktur. Ketika variable struktur dibuat, pengacuan terhadap field individual dibuat deb=ngan pemisahan nama variabel dan nama field oleh tanda titik:
mov dl, srec.stnumber
mov ax, srec.credits
Assembler menambah offset variabel struktur ke offset field dalam struktur untuk membuat alamat efektif. Dalam struktur StudentStruc, offset stnumber adalah 0 karena ini merupakan awal field dalam struktur. Offset kredit adalah 27, offset lastname adalah 7, dan seterusnya.
Jika register basis menunjuk ke variabel struktur, tanda titik memisahkan index dengan field:
mov bx, offset srec
…
…
mov ax, [bx].credits
mov dl, [bx].status
Berbagai mode pengalamatan yang mungkin digunakan:
mov ax, srec[si].credit
mov dl, [bx+si].status
mov dl, srec [bx+di].stnumber
Contoh program Input Struktur. Berikut ini program yang mendemontrasikan struktur, dengan menggunakan beberapa makro dari file MACRO.INC. Program terhubung dengan CONSOLE.LIB dan include file MACRO,INC.
Tile Program Input Struktur
49
dosseg
.model small
.stack 100h
extrn Clrscr:proc
include macro.inc
stnumberSZ = ?
lastnamrSZ = 20
StudentStruc struc
stnumber db stnumberSZ dup(0),0
lastname db lastnameSZ dup(0),0
credit dw 0
StudentStruc ends
.data
srec StudentStruc <>
pspSeg dw ?
progTitle db ‘Contoh Input Struktur Student’
.code
main proc
startup pspSeg
L1 : call ClrScr
display_at 2, 20, progTitle
inputStr 4, 10,‘Student Number : ‘, srec.stnumber, stnumberSz
inputStr 6, 10 ‘Last Name : ‘, srec.lastname,lastnameSz
inputStr 8, 10,’Credits Taken: ‘,srec.credits
locate 12, 10
50
getYN ’More input (Y/n) ?’,’Y’
jxe L1
call ClrScr
exit 0
main endp
end main
Variabel srec mengimplementasikan STRUC yang disebut StudentStruc sehingga pengacuan srec dilakukan dengan format:
srec.stnumber
srec.lastname
srec.credits
Makro inputScr dalam MACRO.INC melakukan input keyboard untuk program ini. Argumen yang dikirim ke mwkro adalah row, columm, prompt, input nama field , danpanjang field. Makro DISPLAY_AT menampilkan string pada baris dan kolom tertentu di layar.
Makro GETYN adalah makro untuk mengambil respons pengguna apakah akan meneruskan lagi atau tidak.
Akhirnya, makro jxe (jump extended equal) diperlukan karena intruksi JE konvensional akan menyebabkan kesalahan “jump out of range”.
PERINTAH RECORD
Perintah RECORD merupakan penjelasan kumpulan bit dalam suatu operand byte atau word. Kita menggunakan perintah ini untuk membuat masking bit dan penggeseran bit lebih mudah. Pertama, record harus didefinisikan dengan nama record dan nama dan lebar setiap field. Sintak untuk pendefinisian record adalah :
Recordname RECORD field [,field] …
Sintak untuk field adalah:
Fieldname : width [= ekspresi]
Fieldname adalah nama filed tertentu dalam record; dan field awal disimpan dalam bit yang paling berarti dari byte atau word.
51
Berikut ini contoh penggunaaan perintah RECORD untuk mendefinisikan susunan bit tanggal 16-bit yang disimpan dalam direktori disk. Tanggal dalam bit-terpetakan, dengan 7-bit untuk tahun, 4 bit untuk bulan dan 5 bit untuk hari:
1111111 1111 11111
Tahun bulan hari
Penggunaan yang sesuai dengan perintah RECORD untuk tanggal adalah:
Date_record record year:7=0, month:4=1, day:5=1
Jika kita mendefinisikan record yang mengandung 8 bit atau kurang, record secara otomatis akan mengacu pada byte-selebihnya, akan mengacu pada word. Jika semua posisi bit tidak digunakan, field bit adalah rapat kanan. Contoh, record berikut hanya mendefinisikan 12 bit. Assembler menset bit posisi rendah dalam field dan menset 4 bit atas tidak bertanda dengan nol:
Bitrec record field1:6=111111b, field2:6=111111b
Nilai seluruh 16 bit adalah:
0000111111111111
Pembuatan Variabel Record. Ketika record telah didefinisikan, mungkin digunakan untuk membuat variabel record. Sintaknya adalah:
[name] recordname <[innitialvalue[,innitialvalue]]…>
Kita dapat memberikan nilai awal pada field tertentu. Jika nilai yang diberikan terlalu besar maka assembler akan menampilkan pesan kesalahan.
Berikut ini contoh variabel record menggunakan definisi date_record di atas, sebagai berikut:
Date_record record year:7=0, month:4=1, day:5=1
…
…
Daterec date_record<>
Dengan cara lain, kita dapat menginisialisasikan daterec dengan 30 May 1990:
Daterec date_record<10, 5, 30>
Penggeseran dan Masking. AKhir dari semuanya, nama field dalam record membantu kita untuk menggeser dan mask dengan lebih mudah. Contoh penyimpanan record 10 Maret 1989:
0001001 0011 01010
Tahun=9 bulan=3 hari=10
52
Misalnya tanggal dipindah ke AX, kita dapat mengisolasi bit yang membuat bulan dengan meng_AND-kan AX kemudian menggesernya ke kanan:
And ax, 0000000111100000b
Mov cl, 5
Shr ax, cl
Operator MASK. Jika kita menggunakan perintah RECORD untuk mendefinisikan date_record kita dapat meningkatkan perintah sebelumnya. Operator MASK membuat mask terhadap bit : semua bit yang berkorespondensi dengan posisi bit diset, dan semua bit lain di nolkan:
Mov ax, file_date
And ax, mask month
Mov cl, month
shr ax,cl
Pada saat date_record didefinisikan, assembler otomatis membuat nilai angka pada masing masing field, tergantung pada nilai penggeserannya. Ini dapat diinterprestasikan sebagai offset bit filed dari posisi nol. Pada contoh sebelumnya, month dipindah ke CL, menyebabkan jumlah penggeseran. Tabel berikut menunjukan nilai geser setiap field:
0 0 0 1 0 0 1 0 0 1 1 0 1 0 1 0
Tahun=9 bulan=3 hari=10
Field Nilai geser
Year 9
Month 5
Day 0
Operator WIDTH. Operator WIDTH mengembalikan jumlah bit dalam field record. Contoh berikut mengakses lembar masing masing field dalam date_record dalam berbagai cara. Berikut ini nilai nilai pada saat assembly :
Date_record record year;7=0, month:4=1, day:5=1
…
Daterec date_record<>
Size_of_year equ width year
Size_of_month equ width month
53
…
…
Mov ax, width day
If(width,date_record) gt 8
Mov ax, daterec
Else
Mov al, daterec
Endif
2.7 CONTOH PENGGUNAAN MAKRO DALAM PROGRAM
.MODEL SMALL
.STACK 300h
ClrScr MACRO ;u/clear screen
Push ax
Push bx
Push cx
Push dx
Mov ah, 06h ;mempersiapkan service & attr layar
Mov cx, 0000h
Mov al, 00h
Mov bh, 07h
Mov th, 24h
Mov dl, 79h
Int 10h ; pakai interrupt 10h
Pop dx
Pop cx
Pop bx
Pop ax
54
ENDM
GotoXY MACRO col,row; u/goto cursor
Push ax
Push bx
Push dx
Mov dh,row ;simpan baris di dh
Mov dl,col ;simpan kolom di dl
Mov ah,02h
Mov bh,00 ;warna biasa
Int 10h ;pakai int 10
Pop dx
Pop bx
Pop ax
ENDM
PrintIt MACRO buffer ;u/cetak ke layar
Push ax
Push dx
Lea dx,buffer
Mov ah,09h ;pakai service 09h u/print string
Int 21h ;pakai int 21h
Pop dx
Pop ax
ENDM
OpenFile MACRO ;u/open file
Mov al,02h
55
Mov ah,3dh ;buka file dengan nama filename
Lea dx,FileName
Int 21h
Mov FileHnad,ax ;simpan penanganannya ke variabel
ENDm ;filehand
ReadFile MACRO ;u/ untuk read file
Mov ah,3fh
Mov bx,FileHand ;dari variabel filehand
Mov cx,81 ;sebanyak 81 karakter
Lea dx,InfoData ;simpan isi file dalam variabel
Int 21h ;infodata
ENDM
CloseFile MACRO ;u/ CloseFile
Mov ah,3eh
Mov bx,FileHand ;varFilehand ditutup
Int 21h
ENDM
SendFile MACRO ;u/ write to file
Mov ah,40h
Mov bx,FileHand ;ke variabel Filehand
Mov ch,0
Mov cl,InfoLine ;sebanyak cx=banyak karakter
Lea dx,InfoData ;karakter yang disimpan diambil dari
Int 21h ;variabel infodata
ENDM
FileIndex MACRO ;u/File pointer
Mov al,02h ;tidak jadi diiplementasikan
56
Mov ah,42h ;karena program tidak dapat melakukan
Mov bx,FileHAnd ;reedit
Mov cx,0h ;fungsi:u/menunjuk ke EOF
Mov dx,0h
Int 21h
ENDM
CreateFile MACRO ;u/ membuat file
Mov ah,3ch
Mov cx,00 ;dengan type file biasa
Lea dx,FileName ;dengan nama filename
Int 21h
ENDM
Clearence MACRO ;u/menghapus editor
Push cx
Mov ch,00
Mov cl,02
RepeatClearence:
Goto XY 00,cl
PrintIt blankLine ;kosongkan baris
Inc cx ;dari baris 2 sampai baris 22
Cmp cx,22 ;dari cl=2 sampai cl=22
jne RepeatClearence
pop cx
ENDM
.DATA
MainMenu DB ‘X:Exit S:Save O:Open$’
BlankLine DB’ $’
57
GiveLine DB
‘============================================$’
Interface DB ‘Tekan ESC untu Menu$’
MsgFileSaved DB ’File Disimpan!$’
MsgFileOpen DB ‘Masukan Nama File:$’
NewLine DB 0AH,0DH,’S’
Space DP 20H,’S’
Columm DB 0 ; menyimpan posisi baris
FileNameInf DB 4 1 dup(‘’),’S’ ;menyimpan posisi kolom
FileStruct LABEL BYTE ;struktur u/ nama file
MaxLen DB 40 ;panjang max namafile
actLen DB ? ;panjang namafile saat ini
filename DB 40 dup(‘’),0 ;isi nam file
InfoStruc LABEL BYTE ; struktur u/ isi file
MLength DB 80 ; panjang maksimum file
InfoLine DB ? ; panjang file saat ini
InfoData DB 81 dup(‘’),’$’ ;isi file
FileHand DW ? ;file handler u/ op.file
.CODE
Start:
Main PROC FAR ;awal program
Mov ax,DGROUP ;tunjuk segmen data
Mov ds,ax
Mov es,ax
CLRSCR ;format layar
58
GoTOXY 00,01
PrintIt GiveLine ;baris 1 memakai garis
GoTOXY 00,22
PrintIt GiveLine ;baris 22 memakai garis
GoTOXY 00,23
PrintIt interface ;tulis help u/ menu
GoTOXY 00,02
Lea dx,InfoStruc ;tunjuk alamat mem u/ file
Mov InfoLine,00 ;set isi buffer mem 0
Input: ;input character
Mov ah,07 ;wait 4 input
Int 21h
Cmp al,1Bh ;esc char check
Je OpenMenu
Cmp al,0dh ;enter check
Je addLine
Cmp al,08h ;Backspace Check
Je ToBackSPACE
Cmp al,20h ;cek apakah input karakter yang legal
Jnl disp ;antara 20h - 7eh
Cmp al,7Eh
Jng disp ;kalau ya, tampilkan ke layar
Jng input ;kalau tidak, minta input lagi
Disp:
Mov dl,al ;display char
59
Mov ah,02
Int 21h
Inc Column ;tambahan counter kolom
Mov InfoData[si],al ;insert to mem
Inc InfoLine ;increment counter
Cmp si,79 ;kalau belum 80 karakter
Jne NextInput ;ulangi proses pengetikan
Jmp Finish ;else keluar
NextInput:
Inc si ;increment string index
Jmp input
ToBackSpace ;Bantuan u/ ke jmp ke
BACKSPACE
Jmp BackSpace
AddLine: ;untuk membuat baris baru
Mov infodata[si],0dh ;+ENTER di mem
Inc si
Inc InfoLine
Inc Line
Mov Column,0
Mov infodata[si],0ah ;+kolom baru di mem
Inc si
Inc InfoLine
Cmp si,79 ;kalau belum 80 char
Jne NextAddLine ;tampilkan newline
Jmp Finish ;else keluar
60
NextAddLine:
Mov ah,09h ;tampilkan baris baru
Lea dx,NewLine
Int 21h
Jmp input
OpenMenu:
GoToXY 0.23 ;bersihkan baris 23
PrintIt BlankLine
GoToXY 0,23
PrintIt MainMenu ;cetak menu
Mov ah,07
Int 21h
Cmp al,’x’ ;cek x
Jne Comps
Jmp Finish ;kalau x exit
CompS:
Cmp al,’s’ ;cek s
Jne CompO
Jmp SaveMe :kalau save
CompO:
Cmp al,’o’ ;cek o
Jne CompRev
Jmp OpenMe ;kalau O open
CompRev:
Cmp al,1 BH ;cek esc
Jne NextOpenMenu ;kalau ya, ulang buat menu
Jmp Revert ;kalau tidak, balik ke mode mengetik
61
NextOpenMenu:
Jmp OpenMenu
SaveMe:
GoToXY 00,24 ;kosongkan baris 24
PrintIt BlankLine
GoToXY 00,24
PrintIt MsgFileOpen ;tampilkan pesan minta file
Lea dx,FileStruc ;load struktur file
Mov ah,0ah ;minta nama file dari keyboard
Int 21h
Mov bh,0
Mov bl,actlen
Mov FileName[bx],’’ ;hilangkan enter pada nama file
CreateFile ;buat filenya
OpenFile ;buka filenya
FileIndex ;ini u/ reedit file
;tidak jadi diimplentasikan
;karena keterbatasan interface
Lea dx,InfoStruc ;load struktur file
SendFile ;simpan ke file
GotoXY 00,24
PrintIt BlankLine ;tampilkan pesan bahwa file
62
GoToXY 00,24 ;berhasil menyimpan file
PrintIt MsgFileSaved
Jmp Revert
OpenMe ;rutin pembacaan file
GoToXY 00,24
PrintIt BlankLine ;kosongkan baris pesan
GoToXY 00,24
PrintIt MsgFileOpen ;pesan minta file
Lea dx,FileStruc ;load struktur file
Mov ah,0ah ;minta file dari input keyboard
Int 21h
Mov bh,0
Mov bl,actlen
Mov Filename[bx’],’$’ ;beri tanda endstr pada nama file
GotoXY 00,00
PrintIt BlankLine
GotoXY 00,04
PrintIt BlankLine GoToXY 00,00
PrintIt FileName ;tampilkan nama file di baris paling atas
Mov FileName[bx],’’ ;tampilkan endstr nama file
Clearence ;bersihkan editor
OpenFile ;buka file
63
Cld ;hapus isi buffer infodata saat ini
Lea di,infodata ;agar tidak mengganggu tampilan
Mov cx,40 ;sebanyak 40x2 karakter
Mov ax,2020h ;isi dengan karakter spasi
Rep stows ;repeat untuk allbyte infodata
Lea dx,InfoStruc ;loda struktur isi file
ReadFile ;baca filenya
GoToXY 00,02 ;pindahkan kursor
PrintIt InfoData ;tulis isi filenya
CloseFile ;tutup file
Jmp Revert ;kembalikan ke mode edit
Revert:
GoToXY 00,23 ;u/ kembali ke mode edit
PrintIt BlankLine ;kosongkan baris ke 23
GoToXY 00,23
PrintIt Interface ;tampilan pesan u/ menu
GoToXY Column,Line ;kembali ke baris editor
Jmp Input ;minta input lagi
Finish:
ClrScr ;bersihkan layar
GoToXY 00,00
64
Mov ah,4ch ;keluar dari program
Int 21h
BackSpace:
Cmp Column,00 ;kalau sudah di awal baris
Je ToInput ;lewati bagian ini
Mov infodata[si],’’ ;hapus tanda karakter backspace
Dec si ;di mem
Dec InfoLine
Dec Column
Mov infodata[si],’’ ;hapus karakter di kiri kursor di mem
GoToXY Column,Line ;pindahkan kursor
PrintIt Space ;hapus karakter di layar
GoToXY Column,Line ;pindahkan kursor
ToInput:
Jmp input
main ENDP
END start
65
BAB III
PENUTUP
3.1 Kesimpulan
Dari penjabaran pemahaman tentang pengertian Makro kiranya diambil kesimpulan
sebagai berikut:
1. Makro (macro) adalah nama simbolik dari string teks atau satu blok kode yang akan
digunakan berulang-ulang dalam program.
2. Makro digunakan dalam program berulangkali sesuai dengan keperluan.
3. Keuntungan mendefinisikan makro adalah perintah ini hanya dibuat sekali: setiap kali
makro dipanggil, assembler membangkitkan perintah di dalamnya.
66