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-puzzle

15 Sliding Puzle

Tampilan awal program saya akan terlihat seperti:

Tampilan Awal Program

Tampilan Awal Program

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:

Tampilan Akhir Program

Tampilan Akhir Program

UML Class Diagram untuk program yang saya buat adalah sebagai berikut:

UML Class Diagram

UML Class Diagram

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.

28 Januari 2012 at 3:36 PM Tinggalkan komentar

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:

Tampilan Hasil Akhir Program

Tampilan Hasil Akhir Program

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:

UML Class Diagram

UML Class Diagram

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..

23 Januari 2012 at 12:21 AM Tinggalkan komentar

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 COMATL 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.

Membuat Project ATL Baru

Membuat Project ATL Baru

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.

ATL Project Wizard

ATL Project Wizard

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.

Tampilan Dialog Add Class

Tampilan Dialog Add Class

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:

ATL Simple Object Wizard

ATL Simple Object Wizard

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…

Menambah Method Pada COM Interface

Menambah Method Pada COM Interface

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:

  1. Beri centang pada checkbox in di Parameter attributes.
  2. Ketik int di Parameter type.
  3. Ketik nilai1 di Parameter name.
  4. Klik tombol Add.
  5. Beri centang pada checkbox in di Parameter attributes.
  6. Ketik int di Parameter type.
  7. Ketik nilai2 di Parameter name.
  8. Klik tombol Add.

Setelah menambahkan parameter, tambahkan nilai kembalian dengan mengikuti langkah ini:

  1. 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.
  2. Beri tanda centang checkbox out dan checkbox retval.
  3. Ketik hasil pada Parameter name.
  4. Klik tombol Add.

Tampilan wizard akan terlihat seperti berikut ini:

Tampilan Add Method Wizard

Tampilan Add Method Wizard

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.

14 Januari 2012 at 1:08 AM 4 komentar

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).

25 November 2011 at 11:43 PM Tinggalkan komentar

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.

20 November 2011 at 1:35 PM Tinggalkan komentar

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

19 November 2011 at 3:48 PM Tinggalkan komentar

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:

Tampilan Notepad

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:

Tampilan Edit.exe

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:

Tampilan VIM

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:

Tampilan VIM line number & wrap on

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).

04 November 2011 at 8:41 PM Tinggalkan komentar

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.

02 November 2011 at 5:41 PM Tinggalkan komentar

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:

Diagram animasi 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:

Clock Signal

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:

SR latch dengan clock signal

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:

D latch

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).

02 November 2011 at 1:10 AM Tinggalkan komentar

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.

31 Oktober 2011 at 7:54 PM Tinggalkan komentar

Tulisan Lebih Lama


Arsip


Ikuti

Get every new post delivered to your Inbox.