Menyelesaikan Sliding Puzzle Dengan Algoritma A*
Pada tulisan ini, saya akan menggunakan algoritma A* seperti pada tulisan sebelumnya. Kali ini algoritma tersebut tidak dipakai untuk mencari jarak terpendek, melainkan untuk menyelesaikan sliding puzzle berukuran 3×3. Sliding puzzle adalah sebuah permainan puzzle dimana pemain harus menggeser kotak-kotak yang ada agar memenuhi konfigurasi tertentu. Sebagai contoh, berikut ini adalah sliding puzzle 15 yang telah berhasil diselesaikan:
15 Sliding Puzle
Tampilan awal program saya akan terlihat seperti:
Program akan menggunakan sebuah file gambar yang telah tersimpan di package co.id.jocki.gambar dengan nama gambar.jpg. Gambar ini akan dibagi ke dalam kotak-kotak sejumlah 8 kotak ditambah 1 kotak kosong. Posisi kotak-kotak tersebut kemudian diacak. Begitu tombol “Solve” di-klik, program Java ini akan mencari solusi dengan langkah minimum, kemudian menampilkan solusi tersebut dalam bentuk animasi hingga mencapai output seperti berikut ini:
UML Class Diagram untuk program yang saya buat adalah sebagai berikut:
Algoritma A* yang dipakai oleh program ini terdapat dalam class Algoritma. Seperti yang diketahui, algoritma A* membutuhkan nilai fungsi g(x) dan fungsi h(x). Pada kode program, fungsi g(x) dihitung oleh method hitungNilaiG(PapanKotak p) dan fungsi h(x) dihitung oleh method hitungNilaiH(PapanKotak p).
Nilai fungsi g(x) adalah berapa jumlah langkah yang dibutuhkan dari awal hingga mencapai PapanKotak dengan posisi masing-masing kotak seperti saat ini. Karena program akan mencari penyelesaian sliding puzzle dengan langkah tersingkat, maka semakin kecil nilai fungsi g(x) akan semakin baik. Setiap PapanKotak memiliki sebuah parent yang mewakili langkah sebelumnya (sebuah PapanKotak sebelum mencapai PapanKotak ini). Dengan demikian, program dapat menghitung nilai fungsi g(x) dengan proses rekursif.
Nilai fungsi h(x) adalah sebuah perkiraan seberapa jauh puzzle mendekati penyelesaian. Program ini akan menghitung nilai h(x) dengan memeriksa jumlah kotak yang berada di posisi yang salah. Semakin banyak jumlah kotak yang berada di posisi yang salah, maka mungkin saja masih banyak langkah yang harus ditempuh. Semakin sedikit jumlah kotak yang berada di posisi yang salah, maka mungkin saja puzzle sudah hampir mendekati penyelesaian.
Setiap PapanKotak yang akan diproses disimpan di sebuah priority queue. Java telah menyediakan class java.util.PriorityQueue<E> yang dapat langsung dipakai. Tentu saja, program harus membuat sebuah Comparator baru untuk memberitahu Java supaya setiap elemen di queue diurutkan berdasarkan nilai fungsi g(x) + h(x).
Program akan melakukan proses berulang hingga menemukan sebuah PapanKotak di priority queue yang berisi solusi (angka 1 berurut hingga 8). Untuk menemukan langkah-langkah yang dibutuhkan dari awal hingga mencapai PapanKotak solusi tersebut, program tinggal membaca parent (step sebelumnya yang juga diwakili sebuah PapanKotak) secara rekursif hingga kembali ke PapanKotak paling awal.
Kode program dapat di-download di link Google Docs berikut. Pastikan untuk men-klik tombol “Download Original” di kanan atas. File zip tersebut merupakan sebuah direktori yang berisi project NetBeans. Untuk menjalankan program tersebut dibutuhkan minimal JDK 7. Bila memakai JDK sebelum versi 7, ganti setiap diamond operator yang ada ke cara lama. Misalnya:
PapanKotak lstHasil = new ArrayList<>();
menjadi
PapanKotak lstHasil = new ArrayList<PapanKotak>();
Bagi yang ingin langsung menjalankan program tanpa source-code, file JAR dapat di-download di link Google Docs ini.
Pencarian Jarak Terpendek Dengan Algoritma A*
~ Happy chinese new year ~ Malam ini penuh dengan semarak kembang api yang tidak berhenti dari tadi. Maklum saja, beberapa menit lagi, tahun Kelinci akan berganti menjadi tahun Naga. Sembari menikmati dentuman kembang api, saya menyempatkan diri untuk menulis mencurahkan isi hati. Topik yang saya pilih kali ini adalah mengenai algoritma. Banyak sekali software engineer yang terbiasa mengimplementasikan business logic, tapi tidak berkutik bila dihadapi dengan ‘soal-soal algoritma’ (termasuk saya!). Yang saya maksud ‘soal-soal algoritma’ disini adalah persoalan dimana si programmer harus mencari jarak terpendek dari satu node ke node lainnya.
Sebagai contoh, saya mengambil gambar-gambar dari scenario Wombat dan ingin menghasilkan program seperti berikut ini:
Pada program tersebut, terdapat sebuah binatang Wombat, sebuah daun, dan batu-batu sebagai penghalang. Wombat dapat berpindah-pindah dari satu kotak ke kotak lainnya, asalkan tidak dihalangi oleh batu. Pertanyaannya adalah bagaimana supaya Wombat dapat mencari jalan untuk menuju ke daun dengan melewati jumlah kotak seminimal mungkin (mencari jarak terpendek)???
Salah satu cara untuk menyelesaikannya adalah dengan menggunakan algoritma A* (baca: A star). Pada algoritma ini, setiap kotak yang mungkin akan dilalui oleh Wombat harus dihitung nilai cost-nya. Nilai cost tersebut umumnya disebut fungsi f(x). Nilai f(x) merupakan penjumlahan dari fungsi g(x) dan fungsi h(x). Secara matematika ditulis f(x) = g(x) + h(x).
Nilai fungsi g(x) adalah nilai cost dari node awal hingga ke node yang saat ini akan dihitung cost-nya.
Nilai fungsi h(x) adalah sebuah nilai heuristic (sebuah perkiraan) yang menerka cost yang dibutuhkan untuk mencapai node tujuan mulai dari node yang saat ini akan dihitung cost-nya.
Saya akan membuat sebuah program Java sederhana, dengan class diagram seperti berikut ini:
Implementasi algoritma A* dapat dilihat pada class Algoritma. Project NetBeans yang berisi implementasi kode program yang ada dapat di-download di sini. Source code pada project tersebut sudah diberi dokumentasi sehingga dapat dipelajari dengan mudah. Saya membuat kode program dengan menggunakan NetBeans 7.1. Selain itu, agar program dapat di-compile, gunakan minimal Java 7, karena saya menggunakan diamond operator yang hanya ada sejak Java 7. Untuk men-download JAR program tanpa perlu men-download source, silahkan klik di sini.
Jam 00.00 telah berlalu. Dentuman kembang api pun mereda. Dan sungguh kebetulan, hujan ikut turun membahasi bumi. Malam pun kembali sepi dan dingin..
Memanggil DLL dari PHP
Pada suatu hari, seorang mahasiswa yang sedang menyusun skripsi menanyakan pada saya apakah mungkin mengakses DLL dari kode program PHP. Sebuah pertanyaan yang tidak terduga, karena saya sama sekali tidak pernah dan tidak berpikiran untuk melakukan hal tersebut. Hal ini karena PHP adalah bahasa pemograman yang berada di banyak platform, gratis, dan sangat populer di Linux. Sementara teknologi DLL adalah teknologi yang sangat terikat pada Microsoft Windows serta Visual Studio-nya. Menurut saya, pertanyaan ‘membaca DLL‘ akan lebih selaras bila dipadukan dengan teknologi ASP.NET dengan bahasa C# ataupun VB, dibandingkan dengan PHP.
Kembali ke pertanyaan semula, apakah mungkin memanggil DLL dari PHP? Setelah melakukan pencarian di PHP Manual, saya menemukan bagian COM and .Net (Windows) yang dapat diakses di www.php.net/manual/en/book.com.php. PHP memang mendukung Component Object Model (COM) dan .NET. Lalu apa hubungan COM dan DLL?
- DLL (Dynamic-link Library) adalah implementasi shared-library di platform Windows. Programmer membuat fungsi yang dapat dipanggil ulang di program berbeda.
- COM (Component Object Model) adalah sebuah metodologi yang mengatur bagaimana menerapkan komponen program yang dapat dipakai ulang di program berbeda.
- COM tidak mengatur struktur bahasa yang dipakai (menurut referensi MSDN, COM sering salah kaprah diangagp sebagai OOP).
- Implementasi COM umumnya dalam bentuk file DLL.
- Tidak semua DLL dibuat berdasarkan aturan COM, atau dengan kata lain tidak semua DLL adalah COM.
Jadi jawaban untuk mahasiswa tersebut adalah: bila DLL dibuat dengan menggunakan teknologi COM, maka DLL tersebut dapat diakses di PHP. Bila DLL tersebut adalah DLL sederhana, maka DLL tersebut tidak dapat diakses di PHP.
Lalu bagaimana bila ingin tetap mengakses DLL sederhana di PHP? Ada sebuah extension PHP yang dikhususkan untuk Windows yang bernama WinBinder. Dengan WinBinder, programmer PHP dapat memanggil semua APIs Windows dengan PHP, membuat program GUI berbasis PHP, bahkan memanggil DLL sederhana (tanpa COM) dengan PHP.
Pada artikel ini, saya akan menggunakan teknologi sebagai berikut:
- Visual C++ di Visual Studio 2010 untuk menghasilkan DLL yang mengikuti spesifikasi COM.
- Memakai ATL (Active Template Library) di Visual C++ untuk membuat COM. ATL bukan bagian dari COM ataupun bahasa C++ melainkan sebuah framework sebagai bagian dari Visual C++ untuk mempermudah pembuatan COM.
- PHP untuk mengakses DLL yang dihasilkan oleh Visual C++
Untuk membuat COM di Visual C++ dengan bantuan ATL, pilih menu File, New, Project di Visual Studio 2010. Kemudian pada Visual C++, pilih ATL Project. Beri nama pada project tersebut, misalnya LatihanCOM. Tentukan juga lokasi folder untuk penyimpanan project tersebut. Kemudian klik tombol OK.
Akan muncul ATL Project Wizard yang terdiri atas dua langkah. Klik tombol Next pada wizard tersebut. Pastikan pada Application Type, pilihan Dynamic-link library (DLL) terpilih. Kemudian klik tombol Finish untuk membuat project.
Setelah project selesai dibuat, buka panel Class View. Bila panel ini tertutup, pilih menu View, Class View (Ctrl+Shift+C) untuk menampilkannya. Klik kanan pada nama project, LatihanCOM, kemudian pilih Add, Class… Pada window Add Class yang muncul, pilih ATL Simple Object. Kemudian klik tombol Add untuk melanjutkan.
Pada tampilan ATL Simple Object Wizard yang muncul, ketik nama Perhitungan di Short name. Nama lain akan di-isi secara otomatis. Pastikan bahwa di bagian COM, nama Interface adalah IPerhitungan. Kemudian isi ProgID dengan nama Jocki.Perhitungan. Window tersebut harus terlihat seperti berikut ini:
Klik tombol Finish untuk menyelesaikan wizard.
Buka panel Class View dan cari COM Interface yang bernama IPerhitungan. Interface ini dibuat secara otomatis oleh Visual C++ sehingga yang perlu kita lakukan hanya menambahkan method yang akan dipanggil oleh program lain. Klik kanan pada IPerhitungan, kemudian pilih Add, Add Method…
Pada dialog Add Method Wizard yang muncul, kita akan membuat sebuah method sederhana. Method ini akan menerima parameter berupa dua buah bilangan bulat, kemudian mengembalikan hasil jumlah dua bilangan tersebut. Pada method name, beri nama HitungJumlah. Kemudian tambahkan dua parameter input dengan mengikuti langkah ini:
- Beri centang pada checkbox in di Parameter attributes.
- Ketik int di Parameter type.
- Ketik nilai1 di Parameter name.
- Klik tombol Add.
- Beri centang pada checkbox in di Parameter attributes.
- Ketik int di Parameter type.
- Ketik nilai2 di Parameter name.
- Klik tombol Add.
Setelah menambahkan parameter, tambahkan nilai kembalian dengan mengikuti langkah ini:
- Ketik int* di Parameter type. Jangan lupa menambahkan * setelah int karena variabel ini akan merujuk ke hasil kembalian (pointer). Bila tidak ada * setelah int, wizard tidak akan memberikan pilihan untuk mencentang checkbox out dan retval di langkah berikutnya.
- Beri tanda centang checkbox out dan checkbox retval.
- Ketik hasil pada Parameter name.
- Klik tombol Add.
Tampilan wizard akan terlihat seperti berikut ini:
Klik tombol Finish untuk menyelesaikan wizard.
Cari baris kode program seperti berikut ini di file Perhitungan.cpp:
STDMETHODIMP CPerhitungan::HitungJumlah(int nilai1, int nilai2, int* hasil)
{
// TODO: Add your implementation code here
return S_OK;
}
Kode program ini merupakan implementasi dari method yang akan dipanggil oleh PHP nantinya. Ganti baris yang diawali dengan //TODO sehingga kode programnya akan terlihat seperti berikut ini:
STDMETHODIMP CPerhitungan::HitungJumlah(int nilai1, int nilai2, int* hasil)
{ *hasil = nilai1 + nilai2;
return S_OK;
}
Langkah terakhir sebelum menghasilkan DLL adalah melakukan sedikit perubahan pada settingan project. Buka panel Solution Explorer. Bila panel ini tertutup, pilih menu View, Solution Explorer (Ctrl+Alt+L). Klik kanan pada nama project, LatihanCOM, kemudian pilih Properties. Pada baris Per-user Redirection, ganti nilai No menjadi Yes. Hal ini dilakukan untuk menghindari hal-hal yang berkaitan dengan masalah hak akses user. Dengan mengaktifkan Per-user Redirection, DLL yang dihasilkan hanya akan tersedia oleh user Windows yang sedang aktif saat ini saja.
Untuk membuat DLL, pilih menu Build, Build Solution (Ctrl+Shift+B). File DLL yang dihasilkan terletak di folder Debug di lokasi penyimpanan project. Sebagai contoh, jika saya menyimpan project di Desktop, maka file DLL yang dihasilkan adalah C:\Users\JockiHendry\Desktop\LatihanCOM\Debug\LatihanCOM.dll. Visual C++ 2010 telah melakukan registrasi DLL secara otomatis sehingga kita tidak perlu repot-repot lagi.
Sekarang, kita akan melakukan pengujian apakah DLL tersebut dapat dipanggil dengan baik. Buat sebuah file PHP dengan isi seperti berikut ini:
<?php
$perhitungan = new COM("Jocki.Perhitungan");
$hasil = $perhitungan->HitungJumlah(11,22);
print "Hasil dari method di COM DLL adalah $hasil";
?>
Bila kode program PHP di atas dijalankan, hasilnya adalah:
Hasil dari method di COM DLL adalah 33
Apa langkah berikutnya?
- Ingin memanggil COM yang berada di komputer lain? Pelajari Distributed COM (DCOM) lebih lanjut.
- Tidak ingin memakai teknologi COM melainkan ingin memakai simple DLL? Lihat solusi yang ditawarkan oleh Winbinder.
- Walaupun Microsoft tidak menghentikan dukungan atas COM, teknologi tersebut sudah kadaluarsa dan kini digantikan oleh penerusnya. Ingin beralih ke .NET? Pelajari lebih lanjut tentang .NET Component.
Membuat bootstrap loader untuk UFD
Pada beberapa mata kuliah seperti sistem operasi dan sistem berkas, dosen mungkin harus mendemokan beberapa komponen low-level yang tidak tersedia pada sistem operasi modern. Seperti yang diketahui, seluruh sistem operasi modern zaman sekarang beroperasi pada CPU protected mode. Hal ini berarti hanya kode program saja yang berada di ring 0, sementara kode program yang dibuat user tidak akan mendapatkan akses ring 0 (kecuali bila diizinkan oleh sistem operasi). Beberapa instruksi assembly seperti IN, OUT, dan beberapa INT umumnya dibatasi oleh sistem operasi. Sebagai contoh, Windows akan menolak instruksi IN/OUT pada program user mode tetapi mengizinkannya pada driver. Sementara di Linux, IN/OUT diperbolehkan bila sebelumnya terdapat pemanggilan ioperm() dan program di-akses dengan hak akses superuser.
Bagaimana bila seseorang ingin tetap menjalankan programnya di CPU real-mode? Ia harus membuat sistem operasi sendiri! Atau untuk sebuah eksperimen sederhana, ia dapat membuat sebuah bootstrap loader yang akan menjalankan sebuah program real mode begitu komputer dinyalakan! Dan untuk eksperimen seperti ini, media UFD (USB Flash Drive) adalah pilihan yang tepat. Kebanyakan BIOS di motherboard zaman sekarang sudah mendukung emulasi disk untuk UFD, sehingga mendukung proses boot dari UFD.
Ini adalah percobaan yang saya lakukan dengan menggunakan sebuah UFD berukuran 4 GB yang menggunakan file system FAT32. UFD tersebut hanya mengandung sebuah partisi. Saya menyalin boot sector dari partisi pertama. Struktur boot sector untuk FAT32 dapat dilihat di http://en.wikipedia.org/wiki/FAT32. Berikut ini kode program assembly (dalam NASM) yang membentuk boot sector di UFD saya beserta dengan bootstrap loader buatan sendiri:
[BITS 16]
[ORG 0x7C00]
jmp mulai
nop
; ------------------------------------------------------
; Informasi Boot Sector
; ------------------------------------------------------
db 'SOS-JCH ' ; OEM name
db 00, 0x2 ; Bytes per sector
db 0x8 ; Sector per cluster
db 0x20, 00 ; Reserved sector count
db 0x2 ; Number of FAT
db 00, 00, 00,00
db 0xF8 ; Media descriptor (F8 = Fixed disk)
db 00, 00
db 0x3E, 00 ; Sectors per track
db 0x7C, 00 ; Number of heads
db 00, 00, 00, 00 ; Count of hidden sectors
db 0xA2, 0xA7, 0x77, 00 ; Total sectors
db 0xDB, 0x1D, 00, 00 ; Sectors per FAT
db 00, 00 ; Mirroring flags
db 00, 00 ; Version
db 0x02, 00, 00, 00 ; Cluster number of root directory start
db 0x01, 00 ; Sector number of FS Information Sector
db 0x06, 00 ; First sector number of a copy of three FAT32 boot sectors
db 00, 00, 00, 00
db 00, 00, 00, 00
db 00, 00, 00, 00
db 00, 00
db 0x29 ; Extended boot signature
db 0xA5, 0x82, 0x1D, 0x86 ; Volume ID
db 'Latihan ' ; Volume Label
db 'FAT32 ' ; File system type
; ------------------------------------------------------
; Starting point
; ------------------------------------------------------
mulai:
; ------------------------------------------------------
; Inisialisasi
; ------------------------------------------------------
cli
xor ax, ax
mov ss, ax
mov sp, 0x7C00
mov ds, ax
mov es, ax
sti
; ------------------------------------------------------
; Menyalin FAT dan menyimpannya ke lokasi offset 0x7E00
; ------------------------------------------------------
mov word [ds:dap_jumlah_sector], 1
mov word [ds:dap_dest_segment], ds
mov word [ds:dap_dest_offset], 0x7E00
mov dword [ds:dap_lba_lo], 94
call bacasector
mov eax, [0x7E08]
mov [fat_next_cluster], eax
; ------------------------------------------------------
; Menyalin RootDirectoryEntry ke lokasi offset 0x8000
; ------------------------------------------------------
mov word [ds:dap_jumlah_sector], 8
mov word [ds:dap_dest_offset], 0x8000
mov dword [ds:dap_lba_lo], 0x3C14
call bacasector
; ------------------------------------------------------
; Mencari File Dengan Nama KERNEL.BIN
; ------------------------------------------------------
proses_cluster_berikutnya:
mov si, 0x8000
pencarian_file_kernel:
push si
lea di, [nama_file_kernel]
cld
mov cx, 11
repe cmpsb
jz file_kernel_ditemukan
;
; File kernel tidak ditemukan pada entry ini.
; Lanjut ke entry direktori berikutnya.
;
pop si
add si, 32
cmp si, 0x9000
jbe pencarian_file_kernel
;
; File kernel tidak ditemukan di cluster ini
; Periksa apakah masih ada cluster berikutnya.
;
mov eax, [fat_next_cluster]
and eax, 0x0ffffff0
cmp eax, 0x0ffffff0
jz hang
mov di, 0x8000
call bacacluster
call bacafat32
jmp proses_cluster_berikutnya
file_kernel_ditemukan:
;------------------------------------------------------------
; Baca File Kernel dan Salin Di Lokasi Memori 0x8000
;------------------------------------------------------------
pop si
mov ax, word [si+0x14]
shl eax, 16
mov ax, [si+0x1A]
mov [fat_next_cluster], eax
mov di, 0x8000
baca_cluster_kernel_berikutnya:
call bacacluster
call bacafat32
mov eax, [fat_next_cluster]
and eax, 0x0ffffff0
cmp eax, 0x0ffffff0
jz start_kernel
add di, 0x1000
mov eax, [fat_next_cluster]
jmp baca_cluster_kernel_berikutnya
;------------------------------------------------------------
; Mulai eksekusi kernel
;------------------------------------------------------------
start_kernel:
jmp 0x8000
hang:
jmp hang
bacafat32:
;
; Baca sebuah sektor FAT32 ke lokasi 0x7E00
; Perhitungan berdasarkan nilai memori [fat_next_cluster]
;
; Mengisi fat_next_cluster dengan nilai
; entry fat berikutnya
; Rumus: sector = 62 + 32 + fat_next_cluster / 128
; offset = (fat_next_cluster % 128 ) * 4
xor eax, eax
xor edx, edx
mov ax, [fat_next_cluster]
mov dx, [fat_next_cluster+2]
mov cx, 128
div cx
push dx ; remainder, untuk offset nanti
add eax, 94;
mov word [ds:dap_jumlah_sector], 1
mov word [ds:dap_dest_offset], 0x7E00
mov dword [ds:dap_lba_hi], 0
mov dword [ds:dap_lba_lo], eax
call bacasector
pop dx
shl dx, 2
add edx, 0x7E00
mov ecx, [edx]
mov [fat_next_cluster], ecx
ret
bacacluster:
;
; Baca cluster data berikutnya.
; eax = nomor cluster
; di = offset tujuan
; Rumus menghitung sector dari cluster:
; s = 62 + 15318 + ((c-2)*8)
;
dec eax
dec eax
mov ecx, 8
mul ecx
xor ecx, ecx
add eax, 15380
adc edx, ecx
mov dword [ds:dap_lba_hi], edx
mov dword [ds:dap_lba_lo], eax
mov word [ds:dap_jumlah_sector], 8
mov word [ds:dap_dest_offset], di
call bacasector
ret
bacasector:
mov ah, 0x42
mov dl, 0x80
mov si, dap
int 0x13
ret
dap db 0x10, 0x00
dap_jumlah_sector dw 0x0001
dap_dest_offset dw 0x0000
dap_dest_segment dw 0x007C
dap_lba_lo dd 0x00000000
dap_lba_hi dd 0x00000000
pesan_salah_fat32 db 'Kernel tidak ditemukan.',0
nama_file_kernel db 'KERNEL BIN'
fat_next_cluster dd 0x00000000
times 510-($-$$) db 0
dw 0xAA55
Directive [BITS 16] memberi tahu NASM bahwa output dari assembly ini adalah kode program real mode 16-bit. Pada saat BIOS selesai menyalin boot sector, ia akan memindahkan IP pada 0x7C00 sehingga instruksi yang akan dikerjakan adalah 0x7C00. Itu sebabnya terdapat directive [ORG 0x7C00].
Assembly di atas jauh dari sederhana, sehingga masih banyak perbaikan yang dapat dilakukan. Salah satunya adalah saya menganggap 1 cluster terdiri atas 8 sector dan 1 sector terdiri atas 512 bytes. Hal ini berlaku pada UFD saya, tetapi mungkin berbeda pada UFD yang di-format secara berbeda. Selain itu, saya menganggap sector yang menampung informasi Root Directory dimulai dari lokasi sector ke 15.318. Saya juga menganggap jarak dari MBR ke boot sector adalah 62 sector. Kode assembly yang lebih baik akan menyertakan proses perhitungan (berdasarkan informasi field di boot sector) sehingga bootstrap loader menjadi fleksibel.
Kode assembly yang ada pada dasarnya akan memeriksa linked list di FAT32 dan membaca seluruh cluster yang berisi informasi Root Directory. Bootstrap loader akan mencari file bernama KERNEL.BIN. Bila file ini ketemu, isi dari file tersebut akan disalin ke lokasi memori 0×8000, dan eksekusi akan dilanjutkan pada lokasi memori tersebut.
Kode assembly di atas dapat diproses menjadi sebuah boot sector dengan menggunakan NASM:
nasm -o boot.bin boot.asm
Output dari perintah di atas adalah sebuah file berukuran 512 bytes dan diakhir dengan 0x55AA. Semuanya memenuhi persyaratan sebuah boot sector. Langkah berikutnya adalah men-copy file tersebut ke boot sector partisi pertama di UFD. Hal ini dapat dilakukan dengan perintah dd di Linux:
$ sudo dd if=boot.bin of=/dev/sdb1 bs=512 count=1
Sebelum mulai restart komputer dan mengatur prioritas boot device di BIOS, pastikan terlebih dahulu bahwa boot flag pada partisi /dev/sdb1 telah di-set menjadi true. Untuk mengatur flag tersebut, seseorang bisa menggunakan perintah fdisk di Linux.
Sekarang, pada saat ingin mencoba kode program real mode, seorang programmer assembly hanya perlu menyimpan program tersebut dengan nama KERNEL.BIN. Setelah itu, copy file KERNEL.BIN ke root directory flash disk. Kini, setiap kali komputer di-boot melalui flash disk, file KERNEL.BIN akan dikerjakan.
Perlu diingat bahwa program real-mode memiliki memori yang terbatas. Akses memori hanya dibatasi pada range 1 MB (bila gate A20 aktif, menjadi 1.114.096 bytes). Area memori ini sudah termasuk yang dipakai untuk Interrupt Descriptor Table (IDT), buffer I/O, dsb sehingga yang tersedia bagi program lebih sedikit lagi. Untuk memakai memori lebih dari 1 MB, programmer harus beralih ke protected mode (itu sebabnya semua sistem operasi modern bekerja pada protected mode).
Menghindari Google Dengan robots.txt
Google sangat bermanfaat bagi banyak orang, memudahkan orang untuk menemukan situs yang dibutuhkannya secara cepat. Akan tetapi, ada kalanya Google bisa jadi berbahaya, terutama bagi pemilik situs. Setiap harinya, program komputer yang disebut Web crawler atau Web robots akan mengunjungi halaman-halaman yang ada di web. Program pintar tersebut akan membaca isi HTML, mencari hyperlink dalam HTML, lalu mengunjungi setiap HTML yang ada dalam hyperlink, dan seterusnya.. Halaman-halaman yang telah dibacanya akan disimpan dalam bentuk index. Dan index inilah yang dipakai bila seseorang melakukan pencarian nantinya.
Bagaimana bila ada halaman tertentu yang tidak penting tetapi ikut ter-index? Atau ada halaman yang bisa di-akses secara publik, tetapi tidak ingin dipublikasikan di Google?
Salah satu cara yang dapat dilakukan adalah dengan membuat file robots.txt di folder root dari situs. File ini harus dapat diakses dengan link seperti www.domain.com/robots.txt
Sebagai contoh, isi file www.facebook.com/robots.txt adalah:
# Notice: if you would like to crawl Facebook you can # contact us here: http://www.facebook.com/apps/site_scraping_tos.php # to apply for white listing. Our general terms are available # at http://www.facebook.com/apps/site_scraping_tos_terms.php User-agent: baiduspider Disallow: /ac.php Disallow: /ae.php Disallow: /album.php Disallow: /ap.php Disallow: /feeds/ Disallow: /l.php Disallow: /o.php Disallow: /p.php Disallow: /photo.php Disallow: /photo_comments.php Disallow: /photo_search.php Disallow: /photos.php User-agent: Googlebot Disallow: /ac.php Disallow: /ae.php Disallow: /album.php Disallow: /ap.php Disallow: /feeds/ Disallow: /l.php Disallow: /o.php Disallow: /p.php Disallow: /photo.php Disallow: /photo_comments.php Disallow: /photo_search.php Disallow: /photos.php User-agent: msnbot Disallow: /ac.php Disallow: /ae.php Disallow: /album.php Disallow: /ap.php Disallow: /feeds/ Disallow: /l.php Disallow: /o.php Disallow: /p.php Disallow: /photo.php Disallow: /photo_comments.php Disallow: /photo_search.php Disallow: /photos.php ... (bagian selanjutnya tidak ditampilkan)
Dengan demikian, setiap kali web crawler dari Baidu, Google, dan MSN (serta lainnya yang tidak ditampilkan di atas) mengunjungi situs, mereka tidak akan mengakses bagian dalam Disallow seperti /photo.php, /album.php, /feeds dan sebagainya.
Untuk menghasilkan file robots.txt secara otomatis, seseorang dapat memakai generator seperti yang ada di http://www.mcanerin.com/EN/search-engine/robots-txt.asp
Satu hal yang harus diperhatikan adalah robots.txt hanya berfungsi sebagai rekomendasi bagi web crawler saja!! Ada beberapa web crawler yang tidak mengindahkan isi robots.txt, terutama web crawler yang memiliki ‘niat buruk’. Crawler seperti ini biasanya disebut bad bots. Bahkan ada bad bots yang dirancang khusus untuk mencari lokasi yang tertuang dalam robots.txt (yang seharusnya tidak boleh dikunjungi). Jadi, robots.txt tidak untuk melindungi halaman yang sensitif. Bila ada halaman yang sangat sensitif yang tidak ingin dilihat oleh orang lain, cara yang paling jitu tetap dengan authentication seperti username dan password, sehingga bad bots yang tidak mengetahui username & password tidak dapat melihat konten tersebut.
URL Rewriting Di Apache HTTP Server
Seorang programmer PHP membuat file latihan.php di folder web-nya. Untuk mengakses file tersebut, pengguna harus mengetikkan URL seperti http://www.domain.com/latihan.php. Dengan demikian, URL selalu berisi informasi yang dipetakan terhadap file fisik. Hal ini tidak berlaku di JEE: user mengakses sebuah Servlet bukan berdasarkan nama class, tetapi berdasarkan nilai element urlPatterns di WebServlet annotation.
Seandainya programmer PHP tersebut membuat file post.php yang diakses seperti ini:
http://www.domain.com/post.php?tahun=2012&bulan=11&tanggal=01
Kemudian ia merasa bahwa URL tersebut terlalu panjang, alangkah sederhananya bila URL tersebut diakses seperti:
http://www.domain.com/2012/10/01
Apa yang harus ia lakukan tanpa membuat file baru? Proses yang harus ia lakukan dikenal sebagai URL rewriting. Bila ia memakai Apache HTTP Server, ia dapat menggunakan Apache mod_rewrite yang menyediakan fungsi tersebut.
Sebelum menggunakan Apache mod_rewrite, pastikan terlebih dahulu modul tersebut sudah di-load, dengan memeriksa isi file konfigurasi Apache. Sebagai informasi, nama file konfigurasi Apache HTTP Server adalah httpd.conf (pada server Linux, biasanya terdapat di direktori /etc). Pastikan baris berikut tidak di-comment (tidak diawali tanda #):
LoadModule rewrite_module modules/mod_rewrite.so
Bila si programmer tidak memiliki akses pada folder sensitif, ia dapat membuat sebuah file PHP dengan isi seperti berikut:
<?php phpinfo(); ?>
Setelah menjalankan PHP tersebut di-browser, sang programmer dapat memeriksa bagian apache2handler di baris Loaded Modules. Bila terdapat tulisan mod_rewrite, maka ia dapat menggunakan fitur URL Rewriting dari Apache HTTP Server.
Langkah berikutnya yang harus dilakukan adalah menambahkan directive untuk keperluan mod_rewrite. Hampir semua directive dapat diletakkan di file konfigurasi httpd.conf, akan tetapi bila si programmer tidak memiliki akses untuk mengubah httpd.conf, ia terpaksa harus meletakkannya pada file .htaccess. Ada beberapa directive yang tidak dapat diletakkan di .htaccess, misalnya RewriteLog dan RewriteLogLevel yang memungkinkan log yang berisi informasi mengenasi proses URL rewriting yang terjadi.
Selain itu, pastikan AllowOverride bernilai All pada directive Directory yang berisi lokasi direktori fisik. Bila AllowOverride bernilai None, maka file .htaccess akan diabaikan oleh Apache HTTP Server.
Langkah terakhir, si programmer membuat file .htaccess di direktori utama, yang isinya seperti berikut ini:
RewriteEngine On
RewriteRule ^([0-9]{4})/([0-9]{2})/([0-9]{2})$ /post.php?tahun=$1&bulan=$2&tanggal=$3
Directive RewriteRule di atas mengandung dua bagian, yaitu bagian Pattern dan bagian Substitution.
Bagian Pattern berisi regular expression yang akan dicocokkan dengan URL yang diberikan oleh pengguna. Pada regex, [0-9]{4}/ menunjukkan bahwa wajib terdapat empat digit angka (contoh pola yang memenuhi: 1994/, 2004/; contoh pola yang salah: abcd/, 19/). Lalu [0-9]{2}/ menunjukkan bahwa wajib terdapat dua digit angka (contoh pola yang memenuhi: 10/, 11/, dan sebagainya). Dengan demikian, secara keseluruhan, contoh nilai yang memenuhi regex di bagian Pattern ini adalah: 2011/11/01
Bagian Substitution berisi resources yang sesungguhnya akan diakses. Resources dapat berupa lokasi file ataupun URL lain. Pada contoh, bila pola URL di pattern dipenuhi, maka yang akan diakses adalah /post.php. Nilai $1 akan digantikan dengan nilai ekspresi dalam tanda kurung yang pertama kali dijumpai di bagian Pattern. Begitu juga nilai $2 akan digantikan dengan nilai ekspresi dalam tanda kurung yang kedua, dan seterusnya.
Dengan demikian, bila user yang memasukkan URL:
http://www.domain.com/2011/11/30
maka halaman yang sesungguhnya diakses adalah:
http://www.domain.com/post.php?tahun=2011&bulan=11&tanggal=30
Memakai VIM di Windows 7
Suatu hari, saya ingin melakukan perubahan konfigurasi domain GlasshFish yang ter-install di Windows 7. Seperti kebanyakan aplikasi multiplatform lain, konfigurasi GlassFish tersimpan dalam sebuah file yang bisa di-edit oleh administrator-nya. Kebanyakan aplikasi multiplatform tidak menyimpan konfigurasi di registry, sehingga pengguna tidak dapat mengedit melalui tools GUI seperti regedit. Hal ini masuk akal, karena registry hanya berlaku di Windows. Cara yang paling efektif dan efisien memang dengan menuliskannya ke dalam sebuah file, karena seluruh platform lain seperti Linux, MacOS, & UNIX, dapat membaca dan menulis isi file.
“Mengedit file” terdengar sangat sederhana, tetapi bagi saya, hal ini menjadi sedikit merepotkan di Windows 7, terutama bila ingin langsung mengedit sebuah file secara langsung tanpa meninggalkan Command Prompt. Selama ini, saya tidak pernah menemukan masalah dalam mengedit file saat berada di console UNIX dan turunannya, karena hampir semua sistem operasi tersebut menyertakan editor teks VI atau VIM. Sejujurnya, saya sedikit kebingungan bila memakai VI, tetapi tidak sulit untuk men-upgrade-nya menjadi VIM (Vi IMproved).
Seandainya, saya sedang berada di Command Prompt Windows 7 (misalnya, untuk memanggil tools asadmin bawaan GlashFish), lalu saya ingin mengedit file konfigurasi domain. Hal pertama yang saya pikirkan adalah notepad.exe, sebuah editor sederhana bawaan Windows dari berbagai generasi. Di Command Prompt, saya bisa mengetikkan seperti berikut ini:
C:\>notepad domain.xml
Akan muncul program Notepad beserta isi file domain.xml seperti berikut ini:
Kenapa setiap baris jadi saling sambung menyambung seperti itu? Di platform UNIX dan turunannya (Linux, MacOS X, dan sebagainya), pemisah baris hanya satu karakter, yaitu karakter LF (Line Feed) yang diwakili karakter ASCII 10 (simbol ‘\n’). Sementara itu, di platform Windows, pemisah baris terdiri atas dua karakter, yaitu karakter CF (Carriage Return) yang diwakili karakter ASCII 13 (simbol ‘\r’) baru diikuti dengan LF (Line Feed). Notepad tidak menemukan karakter ‘\r\n’ sehingga tidak akan ada pemisah baris.
Masih ada sebuah solusi, yaitu editor dalam Command Prompt yang bernama edit.exe. Sungguh tidak disangka editor yang populer di zaman DOS seperti ini masih ada di generasi Windows 7. Untuk memakai edit.exe, saya memberikan perintah seperti berikut ini:
C:\>edit domain.xml
Akan muncul tampilan seperti berikut ini:
Sekarang file sudah dapat dibaca dan ditampilkan dengan rapi. Akan tetapi, edit.exe memiliki banyak kelemahan dalam mengedit file. Salah satunya adalah harus sering menggeser layar (tidak ada fitur word-wrap) dan tidak ada syntax highlighting. Bagaimana bisa fitur editor di Windows kalah dari editor VIM bawaan sistem operasi gratis seperti Linux?
Saya akhirnya memutuskan untuk menginstall VIM versi Windows di Windows 7 saya. VIM dapat didownload di situs resmi-nya. Untuk platform Windows, sudah tersedia installer yang dapat melakukan proses instalasi secara otomatis.
Setelah meng-install VIM, saya menambahkan direktori instalasi VIM di environment variables Path sehingga saya dapat langsung memanggil editor tersebut di Command Prompt. Caranya adalah dengan membuka tab Advanced di System Properties. Kemudian klik pada tombol Environment Variables… Pada dialog yang muncul, cari Path di bagian System Variables, kemudian klik Edit… Saya menambahkan C:\Program Files\Vim\vim73 di bagian paling akhir (pisahkan dengan direktori sebelumnya dengan menggunakan tanda “;“).
Karena saya terbiasa memanggil VIM dengan mengetik vi di Linux, maka saya menambahkan symbolic link vi yang merujuk ke vim.exe. Caranya adalah dengan membuka Command Prompt sebagai superuser (tahan Ctrl+Shift) pada saat men-klik shortcut Command Prompt, lalu berikan perintah seperti berikut ini:
C:\>cd "C:\Program Files\Vim\vim73" C:\Program Files\Vim\vim73>mklink vi.exe vim.exe symbolic link created for vi.exe <<===>> vim.exe
Sekarang, saya dapat mengedit file konfigurasi GlassFish tersebut dengan memberikan perintah seperti berikut ini:
C:>vi domain.xml
Akan muncul tampilan seperti berikut:
Kali ini, saya akan mendapatkan tampilan yang familiar seperti di Linux. Tidak seperti di edit.exe, VIM secara otomatis melakukan word-wrap dan memberikan syntax highlighting (pewarnaan) sehingga lebih mudah mencari bagian yang akan di-edit. Pertama kali memakai VIM memang bisa jadi rumit (tidak ada menu, perintah diberikan dengan mengetikkan huruf seperti :wq untuk save dan keluar). Akan tetapi bila sudah terbiasa, VIM bisa menjadi sebuah editor yang sangat powerful. Misalnya dengan memberikan perintah :set nu! dan :set wrap!, saya dapat mengaktifkan line number dan word wrap sehingga tampilan VIM terlihat seperti:
VIM memiliki banyak fitur menyenangkan lainnya, dan tentu saja, jauh lebih powerful dibanding edit.exe dan Notepad.exe bawaan Windows terutama bagi programmer. Selain itu, VIM juga lebih ringan dan gratis bila dibanding editor berbasis GUI (misalnya editor komersial UltraEdit). Dengan adanya VIM di Windows, akhirnya saya bisa sedikit lebih betah memakai console di Windows (entah mengapa masih merasa tidak seperti di Linux).
Memakai nasm Di Linux
Pada tulisan sebelumnya yang berjudul Assembly di Linux Dengan GAS, saya memperlihatkan penggunaan GNU Assembler di Linux. GNU Assembler (GAS) hampir tersedia di kebanyakan instalasi Linux, sehingga programmer tinggal memakainya saja. Tapi untuk memakai GAS, seseorang harus mempelajari assembly dengan syntax AT&T. Bagi yang terbiasa dengan syntax Intel, pada awalnya mungkin akan sering mengalami sindrom “operand tertukar” (hal ini karena letak operand di syntax AT&T terbalik dengan yang ada di dokumentasi Intel). Sebagai contoh, perhatikan syntax Intel berikut:
mov al, bl
Baris di atas akan memintahkan isi register BL ke register AL. Untuk melakukan hal yang sama pada syntax AT&T, programmer harus memberikan perintah seperti:
movb %bl, %al
Urutan operand yang terbalik seperti ini bisa jadi membingungkan bagi programmer yang sudah terbiasa memakai syntax Intel.
Salah satu solusinya adalah dengan meng-install Netwide Assembler (NASM) yang sangat populer di Linux. Source NASM yang terbaru pada tulisan ini dibuat dapat di-download di situs resmi NASM. Setelah men-download dan men-extract source NASM, kerjakan script configure. Berikan perintah make dan make install untuk meng-install NASM pada lokasi default.
Untuk melihat dukungan format NASM, berikan perintah seperti berikut:
$ nasm -hf ... valid output formats for -f are (`*' denotes default): * bin flat-form binary files (e.g. DOS .COM, .SYS) ith Intel hex srec Motorola S-records aout Linux a.out object files aoutb NetBSD/FreeBSD a.out object files coff COFF (i386) object files (e.g. DJGPP for DOS) elf32 ELF32 (i386) object files (e.g. Linux) elf64 ELF64 (x86_64) object files (e.g. Linux) as86 Linux as86 (bin86 version 0.3) object files obj MS-DOS 16-bit/32-bit OMF object files win32 Microsoft Win32 (i386) object files win64 Microsoft Win64 (x86-64) object files rdf Relocatable Dynamic Object File Format v2.0 ieee IEEE-695 (LADsoft variant) object file format macho32 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files macho64 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files dbg Trace of all info passed to output stage elf ELF (short name for ELF32) macho MACHO (short name for MACHO32) win WIN (short name for WIN32)
Pada Linux, format yang dipakai adalah elf. Perhatikan bahwa NASM mendukung format bin yang akan menghasilkan flat-form binary file (mirip seperti file COM di zaman DOS). Format bin seperti ini dapat dipakai untuk menghasilkan kode untuk bootloader dan berbagai keperluan lain dalam membuat sebuah sistem operasi baru.
Berikut ini adalah program yang sama seperti pada tulisan Assembly di Linux Dengan GAS, hanya saja kali ini memakai Intel syntax dan ditujukan untuk NASM:
section .data output_vendor: db `Vendor ID Prosesor adalah 'xxxxxxxxxxxx'\n` output_vendor_length equ $-output_vendor output_brand: db `Prosesor Brand String adalah 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\n` output_brand_length equ $-output_brand output_no_brand: db `Tidak ada informasi Processor Brand String\n` output_no_brand_length equ $-output_no_brand section .text global _start _start: mov eax, 0 cpuid mov edi, output_vendor mov [edi+27], ebx mov [edi+31], edx mov [edi+35], ecx mov eax, 4 mov ebx, 1 mov ecx, output_vendor mov edx, output_vendor_length int 0x80 mov eax, 0x80000000 cpuid cmp eax, 0x80000004 jl no_brand mov eax, 0x80000002 cpuid mov edi, output_brand mov [edi+30], eax mov [edi+34], ebx mov [edi+38], ecx mov [edi+42], edx mov eax, 0x80000003 cpuid mov [edi+46], eax mov [edi+50], ebx mov [edi+54], ecx mov [edi+58], edx mov eax, 0x80000004 cpuid mov [edi+62], eax mov [edi+66], ebx mov [edi+70], ecx mov [edi+74], edx mov [edi+77], byte 0x20 mov eax, 4 mov ebx, 1 mov ecx, output_brand mov edx, output_brand_length int 0x80 jmp selesai no_brand: mov eax, 4 mov ebx, 1 mov ecx, output_no_brand mov edx, output_no_brand_length int 0x80 selesai: mov eax, 1 mov ebx, 0 int 0x80
Untuk menjalankan program tersebut, berikan perintah seperti berikut ini:
$ nasm -f elf cpuinfo.asm $ ld -o cpuinfo cpuinfo.o $ ./cpuinfo Vendor ID Prosesor adalah 'GenuineIntel' Prosesor Brand String adalah 'Pentium(R) Dual-Core CPU T4400 @ 2.20GHz '
Nilai option “-f elf” menunjukkan bahwa NASM akan menghasilkan output dalam format ELF yang dipakai oleh Linux. Pembuat program assembler yang terbiasa menggunakan IA-32 pun dapat tetap memakai Intel syntax di platform Linux.
Menyimpan Bit Dengan Latch
Sirkuit yang outputnya tergantung pada input sebelumnya disebut sebagai sequential circuit. Ketergantungan dengan input sebelumnya membuat sequential circuit memiliki sifat memori. Salah satu contoh sequential circuit yang ditunjukkan dalam tulisan ini adalah apa yang disebut sebagai latches. Berikut ini adalah diagram sirkuit SR latch:

SR latch adalah sirkuit sederhana yang terdiri atas dua buah NOR gate. Sirkuit ini membutuhkan dua input, yaitu S (Set) dan R (Reset). SR latchmenghasilkan dua output, yaitu Q dan Q’.
Bila nilai S adalah 0 dan R adalah 1, maka nilai Q adalah 0. Hal ini karena R adalah 1 dan NOR gate akan selalu menghasilkan 0 bila salah satu input bernilai 1. Sebaliknya, nilai Q’ adalah 1.
Bila nilai S adalah 1 dan R adalah 0, maka keluaran Q’ selalu 0 sehingga Q bernilai 1.
Bila S bernilai 0 dan R bernilai 0, maka output dari Q dan Q’ akan bergantung pada nilai saat ini:
- Nilai Q adalah 1 dan Q’ adalah 0. Lalu, SR latch mendapat input S berupa 0 dan R berupa 0, maka nilai Q menjadi 1 dan nilai Q’ menjadi 0.
- Nilai Q adalah 0 dan Q’ adalah 1. Lalu, SR latch mendapat input S berupa 0 dan R berupa 0, maka nilai Q menjadi 0 dan nilai Q’ menjadi 1.
Hal ini menunjukkan bahwa:
- Bila Set (S) bernilai 1 dan Reset (R) bernilai 0, maka nilai Q akan menjadi 0.
- Bila Set (S) bernilai 0 dan Reset (R) bernilai 1, maka nilai Q akan menjadi 1.
- Bila Set (S) bernilai 0 dan Reset (R) bernilai 0, maka nilai Q akan selalu sama seperti nilai sebelumnya.
Dengan demikian, sebuah SR latch dapat dipakai untuk menyimpan nilai sebuah bit. Untuk mengatur nilai bit, seseorang perlu memberikan SR = 10 atau SR = 01. Untuk mempertahankan nilai bit tersebut, nilai S tetap 0 dan nilai R tetap 0, maka bit Q akan selalu memiliki nilai yang sama selama listrik masih mengalir. Ini adalah konsep dasar dari sebuah sel 1-bit dalam memori RAM.
Sequential circuit umumnya beroperasi pada synchronous mode. Pada modus ini, seluruh sirkuit dalam sistem mengubah state-nya secara bersamaan pada waktu yang telah ditentukan, melalui penggunaan clock signal. Sebuah clock signal adalah sinyal yang memiliki state 1 (ON) dan 0 (OFF), seperti yang ditunjukkan pada gambar berikut:
Sebuah clock cycle adalah waktu diantara dua buah rising edge (sisi sinyal dari 0 menjadi 1) yang berurutan. Clock rate atau frequency adalah jumlah clock cycle selama 1 detik dalam satuan Hertz (Hz). Dengan demikian, frequency 1 GHz menunjukkan bahwa dalam 1 detik terdapat 1 x 109 clock cycle. Jadi, waktu yang dibutuhkan untuk sebuah clock cycle adalah 1 / (1 x 109) = 1 x 10-9 detik atau 1 ns (nano detik).
Untuk membuat SR latch tersinkronisasi dengan keseluruhan sirkuit lainnya dalam sistem, maka diagram dapat dimodifikasi menjadi seperti pada gambar berikut:
Sekarang, input pada SR latch akan memiliki efek bila terdapat sinyal 1 (ON) dari clock.
D latch adalah jenis SR latch yang menghindari kombinasi S=1 dan R=1. Caranya adalah dengan menggunakan sebuah inverter, seperti yang terlihat di gambar berikut:
Langkah untuk memberi nilai Q pada D latch sama seperti pada SR latch. Setelah itu, nilai Q pada D latch akan terus dipertahankan dengan selama sinyal dari clock adalah sinyal 0 (OFF).
Memakai System Call Linux Di Assembly
Untuk memanggil system call Linux, programmer assembly harus mengetahui nomor definisi system call yang disebut system call numbers. Informasi ini dapat diperoleh dengan membaca file /usr/include/asm/unistd_32.h. Berikut ini adalah contoh isi file tersebut:
#ifndef _ASM_X86_UNISTD_32_H #define _ASM_X86_UNISTD_32_H /* * This file contains the system call numbers. */ #define __NR_restart_syscall 0 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 #define __NR_write 4 #define __NR_open 5 #define __NR_close 6 #define __NR_waitpid 7 #define __NR_creat 8 #define __NR_link 9 #define __NR_unlink 10 #define __NR_execve 11 ... #define __NR_inotify_init1 332 #define __NR_preadv 333 #define __NR_pwritev 334 #define __NR_rt_tgsigqueueinfo 335 #define __NR_perf_event_open 336
Isi file di atas menunjukkan bahwa pada sistem operasi Linux tersebut, terdapat 337 system call yang dapat dipanggil oleh programmer assembly, mulai dari 0 hingga 336. Setelah menemukan system call number, langkah berikutnya adalah menentukan apa saja yang dibutuhkan untuk memanggil system call tersebut. Salah satu cara yang dapat dilakukan adalah dengan memanggil perintah man. Walaupun ditujukan bagi programmer C, informasi yang ditampilkan oleh man cukup berguna bagi programmer assembly yang ingin memanggil system call tersebut. Sebagai contoh, bila programmer ingin melihat informasi untuk system call ber-nomor 4 (didefinisikan sebagai __NR_write), maka ia dapat memberikan perintah:
$ man 2 write NAME write - write to a file descriptor SYNOPSIS #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); ...
Untuk mengerjakan system call di Linux, programmer assembly menggunakan INT dengan nomor interrupt 0×80. Sebelum memberikan INT 0×80, nomor system call (sesuai dengan yang ada di file unistd_32.h) harus diletakkan terlebih dahulu di register EAX, sehingga kernel Linux dapat mengetahui system call apa yang akan dikerjakan. Selain itu, bila ada, nilai parameter harus diberikan pada register tertentu dengan urutan seperti berikut ini:
- Nilai parameter pertama di-isi pada register EBX
- Nilai parameter kedua di-isi pada register ECX
- Nilai parameter ketiga di-isi pada register EDX
- Nilai parameter keempat di-isi pada register ESI
- Nilai parameter kelima di-isi pada register EDI
- Bila jumlah parameter lebih dari lima, EBX mengandung pointer ke lokasi memori yang berisi input parameter secara berurutan.
Pada system call write, informasi yang diberikan oleh man pages menunjukkan bahwa dibutuhkan tiga parameter, yaitu fd, *buf, dan count. Dengan demikian:
- Register EBX mengandung file descriptor (fd)
- Register ECX mengandung pointer ke string yang akan ditampilkan (*buf)
- Register EDX mengandung informasi jumlah karakter di string tersebut (count)
Nilai kembalian dari sebuah system call akan ditampung di register EAX.
Contoh kode program assembly secara lengkapnya akan menjadi:
$ vi test.s .section .data tulisan: .ascii "Ini program pertama saya.\n" .section .text .globl _start _start: movl $4, %eax # System call nomor 4 (write) movl $1, %ebx # Parameter 1: file descriptor = 1 (stdout) movl $tulisan, %ecx # Parameter 2: string yang dicetak movl $26, %edx # Parameter 3: jumlah karakter (26 huruf) int $0x80 # Memanggil kernel Linux movl $1, %eax # System call nomor 1 (exit) movl $0, %ebx # Parameter 1: status code int $0x80 # Memanggil kernel Linux $ as -o test.o test.s $ ld -o test test.o $ ./test Ini program pertama saya.

















