Hidup Untuk Berbagi

Pemrograman Bahasa Assembly

Pemrograman Bahasa Assembly
Pemrograman bahasa assembly sangat erat kaitannya dengan hardware yang digunakan, oleh karena itu tutorial ini diawali dengan penjelasan tentang arsitektur x86. Kita tidak akan mempelajari pemrograman assembly yang rumit, yang akan kita pelajari hanya bagaimana cara membuat file *.com atau yang biasa disebut file flat binary.
Arsitektur Microprocessor x86
Pada bagian ini kita akan membedah bagian-bagian Microprocessor x86 secara fungsional dan mempelajari bagaimana bagian-bagian tersebut bekerja.
Arsitektur Dasar
Dalam sebuah arsitektur komputer ada filosofi tertentu yang digunakan, misalnya dalam hal menentukan apakah kita menggunakan bus yang sama untuk data dan kode program atau keduanya terpisah, dan lain-lain. Secara umum saat ini arsitektur komputer yang ada menggunakan salah satu dari dua “aliran” arsitektur komputer, yaitu Von Neumann Architecture (VNA) dan Harvard Architecture. Pada VNA, bus untuk data dan program adalah sama, sedangkan pada Harvard Architecture, bus untuk data dan program adalah berbeda. Keluarga x86 menggunakan menggunakan VNA yang secara skematik digambarkan sbb:

CPU pada gambar di atas adalah microprocessor yang kita gunakan, memory adalah RAM , dan I/O (Input/Output)devices adalah periferal lainnya, misalnya Video Card, Chipset dan lain-lain. Garis merah tebal pada gambar di atas menunjukkan system bus dari x86, sistem bus ini terbagi menjadi tiga komponen, yaitu data bus, address bus dan control bus. Dari gambar di atas dapat anda lihat bahwa periferal I/O termasuk chipset yang ada di motherboard kita menggunakan bus yang sama dengan bus memory untuk berhubungan dengan microprocessor (system bus). Teknik seperti ini biasa disebut memory mapped I/O, sebab periferal I/O diakses seperti hal-nya kita mengakses memory. Barangkali anda bertanya-tanya, mengapa northbridge ‘hilang’ dari skema di atas, northbridge sebenarnya ada pada pertemuan garis merah tebal dari memory dan I/O devices , chip ini tidak digambarkan sebab chip tersebut “transparan” terhadap program yang kita buat. Maksudnya, chip tersebut tidak akan “mengubah” data apapun yang kita lewatkan melaluinya. Di bawah ini adalah yang skema yang lebih jelas tentang hubungan antara system bus dan microprocessor.

Pada skema di atas anda dapat melihat bahwa system bus terbagi menjadi tiga bagian, yaitu data bus yang digunakan untuk mengirim data dari/ke memory maupun I/O devices, address bus yang digunakan untuk menunjukkan alamat memory atau alamat I/O yang dituju/asal data yang dikirimkan/diterima tersebut tersebut, dan control bus yang digunakan untuk mengatur “status” dari data bus dan address bus, misalnya apakah saat ini kita sedang menulis data ke RAM atau ke I/O devices, apakah kita sedang membaca data dari RAM atau dari I/O devices, dan lain-lain. BIU pada skema di atas adalah Bus Interface Unit, yang mengatur komunikasi microprocessor dengan system bus. ALU adalah Arithmetic and Logic Unit yang berfungsi sebagai komponen untuk melakukan operasi aritmetika dan logika. Registers adalah register-register dari x86, yaitu tempat penyimpanan data sementara (semacam memori) dengan kecepatan sangat tinggi. Register inilah yang akan digunakan dalam pengolahan data di dalam microprocessor. Control Unit adalah komponen yang bertugas mengatur lalu lintas data antara ALU, BIU dan register-register yang ada di dalam microprocessor.
Data di dalam sebuah x86 dapat direpresentasikan dalam bentuk byte (8 bit), word (16 bit) atau dword/double word (32 bit). Ketika mengeksekusi sebuah program, yang terjadi sebenarnya adalah pemindahan data dari memori utama (RAM) ke microprocessor x86, kemudian data ini diolah pada microprocessor dan kemudian di pindahkan ke bagian output yang kita inginkan, misalnya ke ram dari video card atau memori utama, dan lain-lain. Dalam bahasa assembly, kita akan lebih banyak berurusan dengan pengolahan data di dalam microprocessor. Pengolahan data ini melibatkan bagian microprocessor yang disebut register. Register sebenarnya merupakan tempat penyimpanan dan pengolahan data yang ukurannya sangat kecil, tetapi kecepatan akses-nya sangat tinggi. Operasi-operasi yang terjadi terhadap data yang ada pada register-register ini terjadi pada ALU kemudian hasilnya di tempatkan ke register, alamat memori atau alamat I/O, tergantung instruksi yang kita berikan. Jika data yang diolah bertipe “floating point”, maka pengolahannya dapat menggunakan FPU (Floating Point Unit), namun hal ini juga tergantung instruksi bahasa assembly yang kita gunakan. Berikut ini adalah skema dari “isi” sebuah microprocessor x86 generasi ke 6 (i686 yaitu PentiumPro, Pentium II, Celeron, Pentium III, Celeron II):

Pada gambar di atas, bagian kiri yang diberi nama … register adalah isi dari microprosesor itu sendiri dan yang di sebelah kanan, yang diberi label address space adalah memori utama (RAM). Antara microprocessor dan memory utama (RAM) sebenarnya ada yang disebut Bus Interface Unit yang menghubungkan microprocessor dengan bus memory pada Northbridge dan ada pula Northbridge dari motherboard, namun kedua komponen tersebut “transparan” terhadap program assembly yang kita buat, maksudnya, instruksi yang kita buat akan dieksekusi sesuai dengan alamat-alamat yang kita “minta”, jadi kita tidak perlu mengubah-ubah setting dari kedua komponen itu. Gambar di atas menampilkan arsitektur dari x86 secara fungsional. Agar lebih jelas, maka register-register yang ada di bagian kiri gambar di atas di tampilkan lebih rinci :

Dalam pemrograman assembly tingkat awal, kita hanya akan berurusan dengan register-register yang ada di sebelah kiri, sedangkan memori utama yang ada di sebelah kanan tidak terlalu berperan. Tutorial ini hanya akan berurusan dengan General Purpose Register (GPR), tidak akan berurusan dengan Segment Register, sebab hal tersebut telah diatur oleh Software Development Tool yang kita gunakan (Visual C++, Masm atau Nasm). Namun demikian akan tetap ada sedikit penjelasan tentang segment register. Di bawah ini adalah register-register yang termasuk GPR:

Register-register di atas mempunyai fungsi khusus yang agak berbeda. Berikut ini ringkasannya.
1. Register EAX , berfungsi sebagai “akumulator” yaitu register utama yang digunakan untuk menyimpan data sementara yang akan diolah pada ALU atau FPU, register ini juga digunakan sebagai tempat penyimpanan hasil pengolahan data tersebut. EAX dapat mengakses semua register lainnya dan merupakan register dengan akses tercepat, jadi sebisa mungkin kita meletakkan data pada register ini.
2. Register EBX, berfungsi sebagai pointer ke data di memory yang berada pada segmen yang sedang ditunjuk oleh register DS.
3. Register ECX, berfungsi sebagai “counter” (bilangan yang nilainya berubah saat sebuah operasi telah dilakukan) dalam operasi menggunakan string atau dalam perulangan.
4. Register EDX, berfungsi sebagai register untuk melakukan komunikasi data dengan alamat I/O.
5. Register ESI, berfungsi sebagai pointer ke data pada segmen yang sedang ditunjuk oleh register DS. Juga berfungsi sebagai pointer alamat sumber string dalam operasi string.
6. Register EDI, berfungsi sebagai pointer ke data pada segmen yang sedang ditunjuk oleh register ES. Juga berfungsi sebagai pointer ke alamat tujuan dalam operasi string.
7. Register ESP, berfungsi sebagai pointer ke stack (pada segmen yang sedang ditunjuk oleh register SS).
8. Register EBP, berfungsi sebagai pointer ke data yang ada pada stack(pada segmen yang sedang ditunjuk oleh register SS).
9. Register SS (Stack Segment), berfungsi sebagai register yang menyimpan alamat segment stack saat ini. Stack adalah bagian memori utama tempat penyimpanan data sementara jika sebuah fungsi dieksekusi atau sebuah interupsi sedang berlangsung atau pada saat sebuah prosedur dipanggil atau pada keadaan lain saat sebuah program dengan sengaja menyimpan datanya di stack. Biasanya stack berada pada bagian akhir memory (alamat terbesar) dan pointer ke stack (SP) dikurangi setiap kali ada data baru yang di simpan di stack, sesuai dengan ukuran data yang disimpan
Register CS (Code Segment), berfungsi menyimpan alamat segmen tempat kode program yang akan dieksekusi di simpan.
10. Register DS (Data Segment), berfungsi menyimpan alamat segmen tempat data program yang akan dieksekusi di simpan.
Selain fungsi khusus di atas, GPR juga dapat digunakan dalam operasi pengolahan data biasa yang terjadi antara GPR tersebut dengan ALU. Pada tutorial ini, yang akan digunakan secara intensif hanya 4 GPR yang pertama, yaitu EAX, EBX, ECX dan EDX.
Mode Kerja Microprocessor x86
Microprocessor x86 sejak i386 mempunyai 3 macam mode operasi. Mode operasi adalah kondisi operasi Microprocessor tersebut yang menentukan fasilitas apa saja dari Microprocessor yang dapat diakses, misalnya instruksi apa saja yang dapat digunakan, jumlah memory yang dapat diakses dan lain-lain. Mode operasi tersebut adalah (>= i386) :
1. Real Address Mode atau Real Mode. Mode ini hanya digunakan pada saat komputer sedang boot atau saat tidak ada sistem operasi pada komputer yang kita miliki dan hanya bios yang dapat bekerja atau kita sedang menjalankan sistem operasi yang hanya dapat berjalan pada real mode misalnya DOS. Pada mode, tidak semua feature yang dimiliki Microprocessor x86 (>=i386) dapat digunakan. Pada mode ini akses ke hardware secara langsung bebas dilakukan, dan alamat memory yang menyimpan kode sistem operasi juga dapat ditulisi, sehingga sistem dapat dengan mudah crash. Pada mode ini, ukuran register yang digunakan secara default adalah 16 bit, misalnya AX, CX, BX , dan lain-lain.
2. Protected Mode. Mode ini adalah mode yang digunakan saat komputer kita berada dalam sistem operasi protected mode, misalnya windows atau Linux. Pada mode ini seluruh feature x86 (>=i386) dapat digunakan, dan alamat kode program yang “berbahaya”, misalnya sistem operasi tidak dapat diakses, selain itu akses langsung ke hardware tidak diperbolehkan kecuali program kita mendapat ijin dari sistem operasi, misalnya untuk program yang menggunakan device driver. Pada mode ini, ukuran register yang digunakan secara default adalah 32 bit, misalnya EAX, ECX, EBX , dan lain-lain
3. System Management Mode. Mode ini adalah mode power management untuk penghematan daya.
Programer assembly konvensional biasanya menjalankan programnya pada real mode. Namun kita tidak perlu menjalankan komputer kita dengan sistem operasi real mode seperti DOS untuk mencoba program yang seharusnya berjalan pada real mode, sebab pada protected mode (misalnya saat anda sedang menjalankan windows 2000) ada yang disebut virtual-8086 mode, sehingga program yang anda buat “seakan-akan” berjalan pada real mode. Mode ini pada dasarnya adalah emulasi sehingga tidak dijamin semua instruksi dapat dijalankan sesuai dengan yang kita inginkan. Virtual-8086 mode dapat digunakan dengan mudah, yaitu anda tinggal membuat source code assembly kemudian buat executable dan jalankan pada console windows, program itu akan otomatis berjalan pada mode ini jika memang program tersebut memanfaatkan instruksi-instruksi real mode.
Arsitektur x86 Modern
Modern Microprocessor x86 modern seperti Athlon, Pentium III atau Pentium 4 memiliki arsitektur internal yang sedikit berbeda dengan apa yang dideskripsikan di sini sebab microprocessor tersebut sudah begitu kompleks dengan jumlah register yang jauh lebih banyak dan memanfaatkan apa yang disebut superscalar operation, pada salah satu gambar di atas anda melihat ada yang di sebut execution unit, Pentium III mempunyai 3 execution unit semacam ini, Athlon juga mempunyai 3 execution unit seperti ini, jadai anda dapat membayangkan, jika ada 3 instruksi yang tidak saling berhubungan, maka ketiga instruksi tersebut dapat dieksekusi hanya dalam 1 cycle (cycle adalah clock yang dibutuhkan untuk menyelesaikan eksekusi 1 instruksi). Selain itu, pada Microprocessor modern terdapat floating point unit yang mempunyai sangat banyak register, misalnya untuk SSE (Streaming SIMD) terdapat 8 register floating point. Di luar itu semua masih banyak lagi fasilitas yang sebenarnya ada di dalam microprocessor tersebut namun sangat jarang atau bahkan tidak dimanfaatkan, misalnya: sejak microprocessor generasi i686 (PentiumPro), kemampuan mengalamatkan memori yang ada sebenarnya sudah mencapai 64 GB dengan menggunakan apa yang disebut Physical Address Extension (PAE), bukan 4 GB seperti yang saat ini sedang banyak diributkan orang, hanya saja sistem operasi yang benar-benar memberikan dukungan pada kemampuan ini hanya Linux dan Windows 2000 edisi tertentu. Namun kita tidak perlu khawatir bahwa program yang kita buat tidak akan berjalan pada “mesin-mesin” tersebut, sebab semuanya kompatibel ke belakang dengan instruksi yang dibuat untuk “mesin-mesin” generasi sebelumnya.

Sintaks Bahasa Assembly x86
Sekarang kita akan mempelajari sintaks yang digunakan dalam bahasa assembly untuk x86. Tool yang anda butuhkan untuk mencoba contoh-contoh yang ada adalah Nasm atau Microsoft Macro Assembler 6.11, cara menggunakan kedua tool ini akan dijelaskan.
Setiap instruksi yang dapat diubah menjadi machine code oleh assembler disebut sebagai instruction set. Setiap generasi microprocessor mempunyai instruction set yang jumlahnya berbeda-beda, tetapi semuanya memiliki instruction set yang bersifat umum yang dapat dieksekusi pada seluruh microprocessor tersebut. Kita akan menggunakan instruction set yang dapat dieksekusi oleh microprocessor i386 ke atas. Sebelum mempelajari instruction set, terlebih dahulu kita akan mempelajari cara membuat variabel dan konstanta dalam bahasa assembly. Sintaks untuk membuat konstanta adalah:
nama_konstanta equ nilai_konstanta
sintaks ini analog dengan sintaks berikut dalam bahasa C:
#define nama_konstanta nilai_konstanta
contoh:
bank_mask equ 20000840h
akhiran h pada sintaks di atas adalah akhiran yang menunjukkan bahwa nilai tersebut adalah nilai hexadecimal, jika tidak diberi akhiran maka nilai tersebut akan dianggap desimal (basis 10). Anda perlu berhati-hati jika menyatakan konstanta yang nilainya diawali dengan huruf dalam hexadecimal, misalnya: sebuah konstanta bernilai CFCh, maka anda harus memberi awalan 0 saat mendeklarasikannya, jadi hasilnya :
bank_mask equ 0CFCh
Sintaks di atas berlaku baik pada masm maupun nasm. Selanjutnya kita akan mempelajari sintaks untuk membuat variabel, formatnya adalah:
nama_variabel tipe_data nilai_variabel
pada sintaks ini, nama_variabel adalah nama dari variabel yang diinginkan, tipe_data adalah tipe data dari variabel tersebut, dalam bahasa asssembly x86 dikenal beberapa tipe data yaitu:
byte, tipe data ini dapat menyimpan data dengan ukuran 1 byte (8 bit). Sintaks yang digunakan untuk mendeklarasikan variabel dengan tipe ini adalah db
word, tipe data ini dapat menyimpan data dengan ukuran 2 byte (16 bit). Sintaks yang digunakan untuk mendeklarasikan variabel dengan tipe ini adalah dw
dword, tipe data ini dapat menyimpan data dengan ukuran 4 byte (32 bit). Sintaks yang digunakan untuk mendeklarasikan variabel dengan tipe ini adalah dd
contoh:
test db 78h
akhiran h pada sintaks di atas adalah akhiran yang menunjukkan bahwa nilai tersebut adalah nilai hexadecimal. Sama seperti pada deklarasi konstanta, jika anda mendeklarasikan variabel dengan nilai hexadecimal, maka berikan awalan (prefix) 0 jika variabel tersebut nilai varaibel tersebut diawali huruf. Contoh:
test db 0FEh
Perlu anda ketahui bahwa kebanyakan assembler adalah tidak case sensitive. Hal ini perlu anda perhatikan saat memberi nama variabel atau konstanta pada program yang anda buat. Sintaks dasar sebuah pernyataan dalam bahasa assembly adalah :
label: instruction operands ; comment
label pada sintaks di atas adalah opsional. Label biasanya digunakan pada awal instruksi yang akan mengalami perulangan atau pada instruksi yang akan dipanggil dalam sebuah jump. instruction adalah instruksi yang akan dieksekusi, operands adalah variabel yang akan dimanipulasi, jumlah operand tergantung instruksi yang kita gunakan, ada juga instruksi yang tidak mempunyai operand sama sekali. comment adalah komentar, karakter yang ada di belakang tanda titik koma (;) akan dianggap sebagai komentar sampai baris tersebut berakhir. Berikut ini beberapa instruction set yang akan kita pelajari:
Instruction Set Kegunaan
mov dest,src instruksi ini memindahkan isi dari src ke dest. src maupun dest dapat merupakan register atau alamat memory, tetapi salah satunya harus merupakan register, sebab tidak ada instruksi yang dapat langsung memindahkan isi sebuah alamat memory ke alamat memory lainnya.Instruksi ini juga dapat menggunakan operand 8, 16 atau 32 bit.
pushfd instruksi ini digunakan untuk menyimpan isi register flag di stack.
popfd instruksi ini digunakan untuk me-restore isi register flag yang tadinya di simpan di stack dengan instruksi pushfd.
pushad menyimpan isi seluruh register GPR yang pada stack.
popad me-restore isi seluruh register GPR yang tadinya disimpan di stack dengan instruksi pushad.
je label instruksi ini digunakan untuk berpindah (dengan syarat) ke instruksi yang “sejajar” dengan label pada source code yang kita buat. Jika bit ZF (Zero Flag) pada flag register bernilai 1, maka program akan dilanjutkan ke label jika tidak maka eksekusi dilanjutkan ke instruksi selanjutnya setelah je.
jmp label instruksi ini digunakan untuk berpindah (tanpa syarat) ke instruksi yang “sejajar” dengan label pada source code yang kita buat.
inc var instruksi ini digunakan untuk menaikkan nilai yang ada pada register var satu satuan. var adalah sebuah GPR
call proc instruksi ini digunakan untuk memanggil sebuah prosedur, proc adalah label (nama) dari prosedur yang akan kita panggil. Prosedur adalah sekumpulan instruksi dengan fungsi tertentu, kadang disebut juga subrutin .
int num instruksi ini untuk memanggil interupsi bios atau sistem operasi dos. Perlu anda perhatikan bahwa jika kita berada pada mode virtual-8086 maka instruksi seperti ini akan tetap menghasilkan keluaran, tetapi keluaran tersebut sebenarnya adalah hasil emulasi. num adalah nomor dari interupsi yang akan dipanggil
xor dest,src instruksi ini melakukan bitwise xor terhadap src dan dest dan hasilnya disimpan pada dest. src dan dest biasanya merupakan GPR.
lea dest,src instruksi ini menghitung alamat efektif (effective address) dari src dan hasilnya di simpan pada dest. Instruksi ini biasanya digunakan pada operasi string, dest biasanya adalah register si, dan src adalah variabel yang akan dicari alamat efektifnya.
and dest,src instruksi ini melakukan bitwise and terhadap src dan dest dan hasilnya disimpan pada dest. src dan dest biasanya merupakan GPR.
or dest,src instruksi ini melakukan bitwise or terhadap src dan dest dan hasilnya disimpan pada dest. src dan dest biasanya merupakan GPR.
out dest,src instruksi ini adalah instruksi I/O yang mengirim data ke alamat I/O(device), src biasanya register al,ax atau eax yang isinya adalah data yang akan dikirim, dest biasanya adalah register dx yang menunjukkan alamat yang akan dikirimi data.
in dest,src instruksi ini adalah instruksi I/O yang memasukkan data dari alamat I/O (device), src biasanya register dx yang isinya adalah alamat I/O yang datanya akan diambil, dest biasanya adalah register al,ax atau eax, tergantung ukuran operand-nya (data yang akan diterima).
retn Menghentikan eksekusi program dan mengembalikan kontrol program ke instruksi sesudah instruksi pemanggilan rutin ini (sesudah instruksi yang call atau jump yang memanggil rutin ini). Jika bagian sebelum retn ini tidak dipanggil oleh rutin lain maka program diakhiri (sistem operasi mengambil alih kembali kontrol atas komputer).
cmp dest,src instruksi ini digunakan untuk membandingkan dest dan src, jika hasilnya sama maka Zero Flag pada flag register akan di set (diubah menjadi 1).
Untuk instruction set yang lain, anda dapat lihat pada Intel Software Developer’s Manual volume 1: Basic Architecture dan Intel Software Developer’s Manual volume 3: System Programming Guide.
________________________________________
Obrolan bebas:
“Banyak orang berpikir bahwa di jaman seperti ini, saat HLL(High Level Language) seperti C++, Java atau Visual Basic ‘berkuasa’, pemrograman dengan bahasa assembly ‘sudah mati’. Banyak juga orang berpikir untuk apa kita bersusah-susah belajar assembly, kalau HLL sudah ada? Jawaban penulis adalah, saat kecepatan menjadi hal yang sangat krusial maka tak ada yang dapat mengalahkan programming menggunakan bahasa assembly, dan satu lagi, tidak selamanya apa yang kita inginkan dapat kita peroleh dengan HLL. Penulis sendiri sudah beberapa kali menemukan kasus dimana kemampuan mengutak-atik hardware dalam software yang penulis buat tidak dapat disediakan oleh bahasa C atau bahasa lain dalam bentuk API (Application Programming Interface) pada sistem operasi, sehingga pemrograman assembly harus dilakukan. Jadi kita harus ingat bahwa ‘Assembly Programming never die'”
________________________________________
Program Assembly Sederhana
Pada bagian sebelumnya kita telah mempelajari beberapa sintaks assembly, sekarang saatnya menggunakan sintaks tersebut untuk membuat sebuah program sederhana. Program ini akan menampilkan sebuah string pada console jika dijalankan. Berikut ini adalah source codenya:

.386
.MODEL TINY
CSEG SEGMENT PARA PUBLIC USE16 ‘CODE’
ASSUME CS:CSEG
org 100h
start:
;;Routine utama

pushfd ;save flag
pushad ;save isi semua GPR
;; Menampilkan karakter dilakukan melalui interrupt 10h, service 0Eh
;; dari bios video card, karakter yang akan ditampilkan diberikan
;; melalui register si
lea si,msg
mov ah,0Eh ;gunakan service 0Eh
mov bl,07h ;warna foreground
xor bh,bh ;gunakan page 0, akan muncul bug tanpa ini
MORE_DIS:mov al,cs:0+[si] ;karakter yang akan ditulis ada pada al
cmp al,’$’ ;’$’ menandakan akhir string
je NO_MORE_DIS
inc si
int 10h ;panggil int 10h (serice dari video bios)
jmp MORE_DIS
NO_MORE_DIS:
popad ;restore semua GPR
popfd ;restore semua flags
retn ;return / akhiri program
;;Definisi Variabel
msg:
DB 10,13
DB 10,13
DB 0,0,0,0,0,0,0,’Your wish is my command’,10,13,10,13
DB 0,0,0,0,0,0,0,’Tweaking your chipset…’,10,13,’$’
CSEG ENDS
end start

Source code di atas adalah source code dalam masm (Microsoft Assembler). Untuk membuat file *.com dari source code di atas, anda harus meletakkan source code di atas satu direktori dengan ML.exe dan Link.exe dari Masm (penulis menggunakan Masm 6.11) kemudian mengunakan perintah berikut di dalam console windows pada direktori source code tersebut, jika anda belum ada pada direktori source code tsb maka cd ke direktori itu:
ml /AT sourcecode.asm /link /TINY
dengan sourcecode.asm adalah source code tersebut. Anda dapat meng-copy source code di atas, kemudian membukanya dengan Notepad.exe , kemudian menyimpannya dengan ekstensi *.asm. Anda dapat menggunakan editor lain, tetapi editor tersebut harus “netral”, maksudnya tidak menambahkan formatting character ke dalam source code tersebut, misalnya MS Word tak dapat digunakan sebab menyalahi aturan ini (menambahkan formatting character). Program di atas akan menghasilkan output:

Your wish is my command
Tweaking your chipset…

Jadi program yang sangat sederhana ini hanya menampilkan sebuah string di layar (console) saat dieksekusi. Sekarang kita akan membahas apa saja yang dilakukan oleh source code ini. Pada bagian awal source code ini anda melihat:
.386
Sintaks ini maksudnya adalah machine code yang dihasilkan oleh program ini hanya kompatibel (dapat dieksekusi) pada processor i386 atau yang lebih baik. Kemudian sintaks:
.MODEL TINY
maksudnya adalah kita akan membuat sebuah file *.com. File *.com sebenarnya adalah file flat binary, yaitu machine code yang dihasilkan langsung dapat dijalankan. File *.com hanya menggunakan satu segment pada real mode atau mode virtual-8086, itulah sebabnya pada bagian awal program penulis mengatakan bahwa kita tidak perlu pusing dengan segment register sebab kita hanya menggunakan satu segmen saja. Selanjutnya, sintaks:
CSEG SEGMENT PARA PUBLIC USE16 ‘CODE’
ASSUME CS:CSEG
artinya adalah kita menginginkan agar assembler membuat penyataan-pernyataan selanjutnya berada dalam satu segmen saat dibuat machine code yaitu pada CSEG, PARA artinya machine code yang dihasilkan harus diurutkan dalam format 16 bit. PUBLIC USE16 ‘CODE’ artinya adalah machine code yang dihasilkan akan berjalan secara default dalam processor x86 pada real mode (sebab pada mode ini, ukuran register secara default adalah 16 bit), dan segmen sesudah pernyataan ini adalah segmen kode program (lihat kembali penjelasan segment register yaitu CS dan DS). Pada bagian akhir program anda melihat sintaks:
CSEG ENDS
sintaks ini memberitahu kepada masm bahwa kode program untuk code segment (yang berawal pada CSEG … )hanya sampai pada bagian ini saja. Kemudian pernyataan:
org 100h
artinya adalah machine code ini akan ditempatkan pada memory dengan alamat 100h+alamat segmen yang ditunjuk oleh CS. Pernyataan:
start:
adalah sebuah label untuk menandai awal program. Dalam masm, anda harus memberikan sebuah label untuk menandai bagian awal instruksi yang dapat diubah menjadi machine code. Pada bagian akhir program anda melihat sintaks:
end start
sintaks ini untuk menandai bagian akhir dari program yang kita buat. Kedua penanda (marker) ini harus ada agar masm dapat bekerja. Sintaks:
pushfd
pushad
sintaks ini artinya: menyimpan isi dari GPR dan Flag Register ke stack. Tujuannya adalah untuk menghindari kesalahan (bug) saat pernyataan-pernyataan dibawahnya selesai dieksekusi dan kendali komputer kembali ke sistem operasi. Sebelum memberikan kendali ke sistem operasi, program ini me-restore kembali nilai GPR dan flag yang lama dengan instruksi:
popad
popfd
sehingga bug diharapkan tidak akan muncul. Instruksi-instruksi selanjutnya adalah instruksi untuk menampilkan string. String ini disimpan pada sebuah variabel bertipe db (byte). Hal ini dilakukan pada baris:
msg:
DB 10,13
DB 10,13
DB 0,0,0,0,0,0,0,’Your wish is my command’,10,13,10,13
DB 0,0,0,0,0,0,0,’Tweaking your chipset…’,10,13,’$’
baris-baris program ini artinya, kita menyatakan sejumlah variabel bertipe byte dengan msg digunakan sebagai label untuk menandai alamat awal dari kumpulan variabel bertipe byte ini. Pernyataan DB 10,13 adalah sebuah pernyataan definisi dua buah variabel bertipe byte yang nilainya diinisialisasi menjadi 10 dan 13, dan seterusnya dengan variabel-variabel selanjutnya. Variabel terakhir dari kumpulan byte (kumpulan byte seperti ini biasa disebut string sebab isinya adalah karakter) ini berisi karakter ‘$’. Nilai 10,13 berarti karakter CR(Carriage return/Enter) dan LF (Line Feed / baris yang baru). Nilai 0 artinya karakter kosong. String ini ditampilkan dengan perintah:

lea si,msg ;hitung dan pindahkan alamat label msg
;ke register si
mov ah,0Eh ;gunakan service 0Eh
mov bl,07h ;warna foreground
xor bh,bh ;gunakan page 0, akan muncul bug tanpa ini
MORE_DIS: mov al,cs:0+[si] ;karakter yang akan ditulis ada pada al
cmp al,’$’ ;’$’ menandakan akhir string
je NO_MORE_DIS
inc si
int 10h ;panggil int 10h (serice dari video bios)
jmp MORE_DIS
NO_MORE_DIS:
Pada potongan source code di atas, tampilan pada layar dilakukan dengan menggunakan bantuan bios VGA card. Hal ini dilakukan dengan cara memanggil interupsi13 nomor 10h dengan register ah bernilai 0Eh, interupsi ini akan memanggil kode program pada bios vga card untuk menampilkan karakter yang berada pada register al. Register yang dicek oleh interupsi ini (int 10h) selengkapnya sbb:
AH = 0Eh
AL = karakter yang akan ditampilkan
BH = nomor page (halaman), digunakan jika kita menggunakan banyak halaman
BL = warna foreground (hanya pada mode grafik)
Jadi baris program int 10h maksudnya adalah tampilkan karakter dan setting yang sudah kita siapkan (pada register-register yang dicek oleh interupsi ini) ke layar. Untuk menampilkan seluruh karakter digunakan loop pada label MORE_DIS s/d NO_MORE_DIS, di dalam loop ini, karakter yang alamatnya ditunjukkan oleh gabungan register cs dan si dipindahkan terus menerus ke al, dan ditampilkan dengan memanggil interupsi 10h. Hal ini terus diulang sampai karakter yang ada pada al adalah ‘$’, hal ini dapat dilihat pada instruksi cmp al,’$’ , saat karakter ini diperoleh (yaitu pada saat register si menunjuk ke variabel terakhir setelah label msg), program akan keluar ke label NO_MORE_DIS, sebab baris je (jump if equal) akan membuat eksekusi program berpinda ke label NO_MORE_DIS. Jika anda masih bingung, baca kembali deskripsi tentang istruction set yang ada pada bagian sebelumnya untuk memahami apa saja yang dilakukan oleh setiap instruksi.
________________________________________
Catatan:
13Interupsi adalah sebuah mekanisme untuk mengalihkan eksekusi program untuk menjalankan kode program yang sudah disediakan oleh bios atau sistem operasi atau hardware (microprocessor), kode program ini biasa disebut Interrupt Handler. Pada saat interupsi terjadi, “state” processor, yaitu data-data yang ada pada register-register semuanya di simpan pada stack dan sistem mengeksekusi interrupt handler. Interrupt handler menyediakan “service” kepada software yang kita buat untuk hal-hal tertentu yang sering dilakukan,misalnya tampilan ke layar atau membaca sesuatu dari hard drive, dan lain-lain. Untuk mengetahui tentang nomor interupsi dan apa yang dilakukan, silahkan mencari daftar interupsi di buku pemrograman atau di web, jika anda ingin mencari di web maka gunakan search engine dengan keyword “Ralph Brown interrupt list” atau “interrupt list”, dengan keyword ini kemungkinan besar anda akan sampai ke situs yang menyimpan interrrupt list dari Ralph Brown. Daftar inilah yang, merupakan daftar interupsi paling lengkap untuk x86.
________________________________________
________________________________________
Obrolan bebas:
“Penulis mohon maaf karena pada tulisan kali ini belum dapat membahas penggunaan Nasm untuk program di atas. Hal ini disebabkan oleh waktu yang terbatas untuk membuat tutorial ini.”
________________________________________

Penggunaan Assembly dan C dalam satu Program
Pada bagian ini kita akan membahas bagaimana menggunakan sintaks bahasa assembly di dalam sebuah program yang menggunakan bahasa C. Untuk memulai pembahasan, kita akan membedah potongan source code driver yang telah kita bahas sebagian sebelumnya.

void PatchPCI(ULONG reg_addr, ULONG mask)
{
//Patch the chipset
__asm
{

pushfd ;//save all flags and regs
pushad
mov eax,reg_addr ;//fetch the address of the regs to be patched
mov dx,PCI_ADDR_PORT ;//fetch the input port addr of PCI cfg space
out dx,eax
mov dx,PCI_DATA_PORT
in eax,dx
or eax,mask ;//mask the regs value (activate certn. bits)
out dx,eax
popad ;//restore all flags
popfd
}
}

Pada source code di atas ada keyword baru, yaitu __asm. Keyword ini digunakan untuk memberi tahu compiler Visual C++ bahwa instruksi pada pernyataan atau blok pernyataan selanjutnya adalah instruksi assembly (ingat kembali bahwa blok pernyataan dibatasi oleh kurung kurawal / {}). Jadi, hanya keyword (ditambah {} jika anda ingin mengeksekusi blok pernyataan assembly) ini saja yang anda butuhkan untuk menambahkan instruksi assembly ke source code anda.
Selanjutnya aspek teknis yang harus anda perhatikan adalah, source code di atas akan berjalan pada device driver dalam windows. Jadi microprocessor kita telah berada pada protected mode, dengan demikian ukuran default register-register yang tersedia bagi programer assembly adalah 32 bit, jadi GPR yang tersedia adalah EAX, ECX, EBX,EDX, dst. Sekarang pembahasan source code di atas. Dua instruksi pertama dan dua instruksi terakhir sudah dibahas sebelumnya. Instruksi selanjutnya adalah:
mov eax,reg_addr
instruksi ini memindahkan isi variabel reg_addr ke register EAX, reg_addr adalah variabel input yang diberikan oleh fungsi yang memanggil fungsi PatchPCI. Instruksi selanjutnya, yaitu:
mov dx,PCI_ADDR_PORT
mengisi register dx dengan konstanta PCI_ADDR_PORT. Instruksi berikutnya:
out dx,eax
mengirimkan data yang ada pada register eax ke alamat yang ditunjuk oleh register dx (pada baris sebelumnya alamat ini telah dimasukkan). Instruksi selanjutnya telah kita bahas sebelumnya. Kemudian instruksi:
in eax,dx
mengambil data dari alamat yang ditunjukkan oleh register dx. Instruksi berikutnya:
or eax,mask
melakukan operasi bitwise or dengan variabel mask yang diperoleh dari parameter kedua fungsi PatchPCI, dan hasilnya disimpan pada register eax. Baris-baris selanjutnya dapat anda pahami dari pembahasan sebelumnya. Untuk memperjelas konsep yang sudah anda pelajari, berikut ini diberikan sebuah contoh program sederhana.

#include
typedef unsigned int UINT;
UINT tambah(UINT suku1, UINT suku2);
void main()

{
UINT suku1;
UINT suku2;
UINT hasil_operasi;
printf(“ketikkan suku pertama : “);
scanf(“%d”,&suku1);
printf(“ketikkan suku kedua : “);
scanf(“%d”,&suku2);
hasil_operasi= tambah(suku1,suku2);
printf(“Hasil penjumlahan kedua suku itu adalah : %d \n”, hasil_operasi);
}
UINT tambah(UINT suku1, UINT suku2)
{
UINT hasil;
__asm
{
pushfd ;/* simpan isi register flag */
pushad ;/* simpan isi GPR*/

mov eax,suku1 ;/* kopi suku1 ke eax 8 */
add eax,suku2 ;/* jumlahkan suku2 ke suku1, simpan hasil di eax */
mov hasil,eax ;/* kopi hasil penjumlahan ke variabel hasil*/
popad ;/* restore kembali isi GPR */
popfd ;/* restore kembali isi register flag */
}
return hasil;
}

Contoh keluaran dari program ini adalah:

ketikkan suku pertama : 5
ketikkan suku kedua : 9
Hasil penjumlahan kedua suku itu adalah : 14

Program di atas dapat anda coba. Source code tersebut tidak akan dijelaskan lagi oleh penulis sebab cukup mudah dipahami dan komentar yang ada pada source code nya cukup jelas. Sampai di sini anda sudah dapat membuat sebuah program yang memanfaatkan bahasa assembly dan C sekaligus, tetapi perhatikan bahwa sintaks di atas hanya berlaku untuk Visual C++, untuk Software Development tool yang berbeda, anda harus membaca lagi dukumentasinya.
________________________________________
Obrolan bebas:
“Selamat! Sekarang anda sudah dapat membuat program dengan bahasa C dan assembly, anda tinggal berlatih untuk membuat diri anda semakin terampil🙂. Untuk memperdalam ilmu anda, anda dapat membaca referensi yang penulis cantumkan. Penulis menyadari bahwa pada tutorial ini masih banyak yang kurang jadi tutorial ini akan diupdate jika penulis sudah punya waktu lagi agar semakin bermanfaat dan mudah dipahami.”
________________________________________
ARG Agree to run garbage
BBT Branch on binary tree
BBW Branch both ways
BEW Branch either way
BH Branch and hang
BMR Branch multiple registers
BOB Branch on bug
BOD Beat on drum
BOI Byte operator immediately
BPDI Be polite, don’t interrupt
BPO Branch on power off
BST Backspace and stretch tape
CEMU Close eyes and monkey with user space
CLBR Clobber register
CLBRI Clobber register immediately
CM Circulate memory
CPAR Crumple paper and rip
CRB Crash and burn
CRR Convert to Roman Numerals
CU Convert to unary
CZZC Convert zone to ZIP code
DC Divide and conquer
DWIMNWIS Do what I mean, not what I say
DMPK Destroy memory protect key
DNPG Do not pass go
DO Divide and overflow
EIOC Execute invalid opcode
EMPC Emulate pocket calculator
EPI Execute programmer immediately
EROS Erase read-only storage
EXOP Execute operator
EXPP Execute political prisoner
FSRA Forms skip and run away
GFD Go forth and divide
GFM Go forth and multiply
HCF Halt and catch fire
IBP Insert bug and proceed
IIB Ignore inquiry and branch
LCC Load and clear core
MBF Multiply and be fruitful
MLR Move and lose record
PBC Print and break chain
PD Play dead
PDSK Punch disk
PI Punch invalid
POPI Punch operator immediately
PS* Punch obscenity
PSD Pause and smoke dope
PVLC Punch variable length card
RAT Random Access Tape
RD Reverse directions
RDS Read sideways
RIRG Read inter-record gap
RPM Read programmer’s mind
RSC Read and shred card
RSD On read error self destruct
RSTOM Read from store-only memory
RWCR Rewind card reader
SDJ Send data to Japan
SHAB Shift a bit
SHLBM Shift a little bit more
SMK Send money to Koen
SMR Skip on meaningless result
SOT Sit on a tack
SQSW Scramble program status word
SQPC Sit quietly and play with your crayons
SRSD Seek record and scar disk
SRZ Subtract and reset to zero
SSJ Select stacker and jam
STROM Store in read-only memory
TDB Transfer and drop bits
UER Update and erase record
WBT Water binary tree
WEMG Write eighteen-minute gap
WPM Write programmer’s mind
XSP Execute systems programmer
ZAM Zero all memory

Berikut adalah jenis-jenis register yang ada pada prosesor Intel.
Kategori Nama Penjelasan
General Purpose EAX, EBX, ECX, EDX Lebar data 32 bit, boleh diapakai untuk keperluan apa saja. E adalah Extended (karena awalnya register general purpose hanya 16 bit).
AX,BX,CX,DX 16 bit bawah dari register 32 bit di atas. AX adalah bagian 16 bit bawah dari EAX.
AH,AL,BH,BL,CH,CL,DH,DL Bagian 8 bit dari register 16 bit di atas . AH adalah 8 bit atas dari AX. AL adalah 8 bit bawah dari AX.
Segment Register CS, SS, DS, ES, FS, GS Digunakan untuk menunjuk 16 bit awal alamat memori. CS = Code, SS = Stack, DS = Data, ES,FS,GS = Extra segment register
Offset Register Digunakan untuk menunjuk 16 bit akhir alamat memori. Alamat memori ditunjukkan dengan gabungan segment dan offset.
EBP Dipakai sebagai offset frame dalam stack. Biasanya menunjuk pada bottom of stack frame di suatu fungsi. ESP menunjukkan puncak stack, EBP menunjuk dasar stack.
ESI Biasanya dipakai untuk offset string sumber dalam operasi yang melibatkan blok memori.
EDI Biasanya dipakai untuk offset string tujuan dalam operasi yang melibatkan blok memori.
ESP Stack pointer, menunjukkan puncak dari stack.
Special EFLAGS Tidak bisa dipakai programmer, hanya dipakai prosesor untuk hasil operasi logical dan state.
EIP Tidak bisa dipakai programmer, hanya dipakai prosesor untuk menunjukkan alamat memori yang berisi instruksi berikutnya yang akan dieksekusi.

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s