Awalnya
terkesan sangat sulit untuk memahami cara kerja memori komputer. Tapi,
ingat saja, komputer itu hanyalah sebuah kalkulator raksasa yang
memiliki memori sebagai tempat sementara untuk menyimpan hasil
perhitungan. Tempat-tempat ini diberikan indeks nomor (alamat)
untukmemudahkan penggunaannya. Bayangkan saja, prosesor Intel x86 yang
banyak digunakan saat ini menggunakan 32-bit skema alamat. Itu berarti
ada 2^32 (4,294,967,296) kemungkinan tempat yang dapat digunakan sebagai
tempat penyimpanan hasil perhitungan tersebut.>>
Berikut merupakan hal-hal yang berkaitan dengan cara kerja memori:>>
Pointer >>
Pointer
merupakan satu tipe variabel yang khusus, digunakan untuk menyimpan
alamat lain dalam memori untuk mereferensi informasi lain. Karena memori
tidak dapat dipindahkan, informasi ini harus dikopi. Akan tetapi akan
sangat sulit secara perhitungan untuk mengkopi satu informasi di dalam
memori untuk digunakan di fungsi atau tempat lain. Begitu juga dilihat
dari sudut pandang memori. Karena untuk mengkopi suatu data, maka memori
akan membuat satu blok khusus untuk data tersebut, yang tidak dapat
digunakan untuk menyimpan data lain.>>
Pointer
adalah salah satu solusinya. Memori hanya perlu membuat satu variabel
pointer yang diasosiasikan dengan satu blok besar yang menyimpan
informasi tersebut, lalu pointer tersebut dapat dikopi ke semua fungsi
atau tempat yang ingin mengakses blok informasi ini.>>
Register>>
Prosesor
memiliki satu jenis memori khusus yang relatif kecil. Memori ini
disebut Register, dan ada beberapa register khusus yang digunakan untuk
menjejaki hal-hal ketika program dieksekusi. Salah satu yang patut
disebut adalah EIP, Extended Instruction Pointer. EIP merupakan pointer
yang menyimpan alamat dari instruksi yang sedang dieksekusi. Register
lain yang digunakan sebagai pointer adalah EBP (Extended Base Pointer)
dan ESP (Extended Stack Pointer). EBP merupakan pointer yang menyimpan
alamat terakhir (teratas) dari satu segmen memori yang disebut stack,
sedangkan ESP merupakan pointer yang menyimpan alamat stack frame
berikut yang akan dieksekusi. Kita akan membahas kedua pointer ini lebih
jauh lagi pada bagian Segmentasi Memori sebentar lagi.>>
Deklarasi Memori>>
Pada
bahasa pemrograman tingkat tinggi seperti Bahasa C, variabel
dideklarasikan berdasarkan tipenya (seperti: integer, character, float,
dll) masing-masing. Hal ini dilakukan untuk memberitahukan memori berapa
besar ruang yang harus disiapkan untuk menyimpan variabel tersebut.
Misalnya, integer merupakan 4 byte data, yang berarti harus ada 32 (4
byte x 8 bit/byte) bit ruang kosong di memori yang harus dialokasikan
untuk variabel ini. Contoh lainnya adalah tipe character, yang
memerlukan 8 (1 byte x 8 bit/byte) bit ruang.>>
Sebagai
tambahan, variabel juga dapat dideklarasikan dalam bentuk array
(senarai). Array merupakan list (senarai) dari N buah elemen spesifik
data. Jadi, sebuah 10 character array hanya merupakan 10 variabel
character yang disusun berurutan dalam memori. Array juga disebut
sebagai buffer, dan character array juga disebut string. Mengkopi buffer
yang berukuran besar memerlukan waktu dan perhitungan yang lama. Karena
itu, pointer sering digunakan untuk menyimpan alamat memori yang
menjadi awal buffer. Berikut adalah contoh pendeklarasian variabel dalam
bahasa pemrograman C:>>
int variabel_integer;>>
char variabel_character;>>
char character_array[10];>>
char *buffer_pointer;>>
Little Endian>>
Salah
satu yang perlu diingat dalam memori di prosesor x86 adalah urutan
penyimpanan 4 byte data (seperti integer dan pointer) di dalam memori.
Urutan ini disebut Little Endian, yang berarti data byte yang paling
kecil disimpan terlebih dahulu.>>
Misal,
sebuah 4 byte data (digambarkan dengan data hexadecimal atau 16 bit),
0×12345678. Data “12″, “34″, “56″, dan “78″ masing-masing merupakan 1
byte data (pada penulisan 16 bit data, 1 digit angka digambarkan dengan 4
bit). Pada saat disimpan dalam bentuk Little Endian akan berbentuk
seperti berikut: 0×78563412.>>
Segmen Dalam Memory:>>
Memori
program terbagi atas 5 segmen: text, data, bss, heap, dan stack.
Masing-masing segmen mempunyai tempat yang khusus dalam memori untuk
mencapai tujuan yang khusus.>>
Segmen Text>>
Segmen
text juga disebut segmen code. Di segmen ini disimpan instruksi bahasa
mesin hasil kompilasi dari bahasa asembli. Eksekusi instruksi dalam
segmen ini dilakukan secara non-linear. Pada saat program dieksekusi,
EIP diset ke instruksi pertama pada segmen text. Processor kemudian
mengikuti aturan loop seperti di bawah ini dalam mengeksekusi program:>>
Baca instruksi di alamat yang ditunjukkan oleh EIP (instruksi pertama pada awal eksekusi)>>
Tambahkan
sejumlah byte instruksi yang dibaca ke EIP (defaultnya adalah EIP
adalah linear walaupun dalam kenyataan tidak selalu demikian )>>
Eksekusi instruksi yang dibaca pada step 1>>
Kembali ke step 1>>
Kadang,
instruksi yang dieksekusi merupakan instruksi “jump” atau “call” yang
mengubah EIP ke alamat memori yang berbeda. Jadi jika EIP berubah pada
step 3, processor tetap akan kembali ke step 1 dan membaca apa pun
instruksi yang ada di alamat baru tersebut.>>
Segmen
ini tidak dapat ditulisi karena hanya berisi kode-kode program. Hal ini
mencegah orang mengubah kode program selama program berjalan. Ketika
segmen ini dicoba untuk ditulisi, maka program akan memberikan
peringatan kepada user dan program akan berhenti. Perlu dicatat juga
bahwa segmen memori ini mempunyai ukuran yang tetap.>>
Segmen Data dan BSS>>
Segmen
data dan bss digunakan untuk menyimpan variabel program yang bersifat
global atau statis. Segmen data diisi dengan variabel global, string,
dan konstanta lain yang sudah diinisialisasi yang digunakan di
keseluruhan program. Sedangkan segmen bss diisi dengan variabel yang
belum diinisialisasi. Walaupun segmen ini dapat ditulisi, pada dasarnya
ukurannya juga tidak berubah.>>
Segmen Heap>>
Segmen
heap digunakan untuk variabel program lainnya. Satu hal yang perlu
dicatat adalah ukuran segmen heap ini dapat berubah sesuai dengan
kebutuhan. Heap akan bertambah atau menyusut sesuai dengan jumlah memori
yang dipergunakan di dalam program yang sedang berjalan. Pertumbuhan
heap bergerak dari alamat memori yang kecil menuju yang besar.>>
Segmen Stack>>
Sama
seperti heap, stack juga mempunyai ukuran memori yang berubah-ubah
sesuai dengan jumlah ruang yang dipergunakan. Stack dipergunakan untuk
menyimpan konteks sementara pada saat pemanggilan fungsi (function
calls). Pada saat program memanggil fungsi lain, fungsi tersebut akan
diberikan satu set variabel yang diperlukan. Fungsi itu sendiri berada
di lokasi yang berbeda pada segmen text/code. Karena konteks dan nilai
EIP berubah pada saat fungsi dipanggil, stack digunakan untuk mengingat
semua variabel yang diserahkan kepada fungsi, dan juga ke mana EIP akan
dikembalikan setelah fungsi selesai dieksekusi.>>
Segmen
stack pada memori memiliki struktur FILO (First In Last Out), yang
berarti data yang pertama kali dimasukkan ke dalam memori ini akan
menjadi data yang terakhir kali dikeluarkan. Seperti dijelaskan
sebelumnya, register ESP digunakan untuk menjajaki ujung akhir (data
yang terakhir masuk) dari alamat memori pada Stack. Pada saat fungsi
dipanggil, beberapa hal dimasukkan ke dalam stack bersama-sama dalam
suatu struktur yang dinamakan stack frame. EBP register dipergunakan
untuk membuat referensi terhadap Stack Frame yang sedang dipergunakan.
Setiap Stack Frame berisi parameter-parameter terhadap fungsi tersebut,
variabel lokal fungsi tersebut, serta dua pointer yang diperlukan untuk
mengembalikan segala sesuatunya seperti semula setelah fungsi selesai
dijalankan. Kedua pointer ini adalah Saved Frame Pointer (SFP) dan
Return Address (RA). SFP berguna untuk mengembalikan nilai EBP ke
kondisi awal sebelum fungsi dijalankan. Sedangkan RA digunakan untuk
mengembalikan EIP ke instruksi berikutnya setelah fungsi dijalankan.>>
Ada baiknya kita menggunakan 2 fungsi berikut untuk menjelaskan cara kerja Stack:>>
void test_function (int a, int b, char c){>>
char flag;>>
char buffer[10];>>
}>>
void main () {>>
test_function(1,2,’a');>>
}>>
Di
permulaan program ini, fungsi test_function yang memerlukan 3 parameter
yang dideklarasikan sebagai integer (a dan b) serta satu character (c).
Kemudian, fungsi ini juga memiliki variabel lokal yang dideklarasikan
sebagai character (flag) dan satu larik character (buffer). Pada saat
program berjalan pertama kali, maka fungsi main akan dieksekusi yang
kemudian akan memanggil fungsi test_function.>>
Pada
saat fungsi test_function dipanggil, ada beberapa nilai yang dimasukkan
ke dalam Stack untuk membuat Stack Frame. Dalam Stack, data dimasukkan
secara terbalik. Data 1,2, dan ‘a’ akan dimasukkan dengan posisi ‘a’, 2,
1. Parameter ini dinyatakan dengan variabel c, b, dan a pada
test_function.>>
Ketika
instruksi “call” dari bahasa assembly dieksekusi, konteks eksekusi
program akan berpindah dari fungsi main ke fungsi test_function, karena
itu alamat si pemanggil (main) perlu dimasukkan ke dalam stack. Alamat
ini merupakan alamat berikutnya dari EIP, atau alamat yang ditemukan
pada step 3 dari eksekusi loop pada segmen text yang sudah dijelaskan di
atas. Setelah memasukkan alamat pemanggil (return address) ini, maka
dimasukkan nilai Saved Frame Pointer (SFP) yaitu nilai EBP pada saat
ini. Ini dilakukan untuk mengembalikan posisi stack ke kondisi
sebelumnya setelah eksekusi test_function selesai. Kemudian nilai EBP
diperbaharui dengan nilai Frame Pointer yang terbaru. Setelah itu,
barulah variabel lokal pada fungsi test_function dimasukkan ke dalam
Stack dengan menggunakan nilai ESP (Extended Stack Pointer) sebagai
patokan.>>
>>
source:
0 komentar:
Posting Komentar
Catatan: Hanya anggota dari blog ini yang dapat mengirim komentar.