Untuk menjawab pertanyaan yang telah Anda posting di beberapa komentar (yang saya pikir Anda harus mengedit posting Anda):
Apa yang saya tidak mengerti adalah bagaimana komputer tahu memungkinkan ketika membaca nilai variabel dari dan alamat seperti 10001 jika int atau char. Bayangkan saya klik pada program yang disebut anyprog.exe. Segera kode mulai dijalankan. Apakah file exe ini menyertakan informasi tentang apakah variabel disimpan sebagai atau karakter?
Jadi mari kita menaruh beberapa kode padanya. Katakanlah Anda menulis:
int x = 4;
Dan mari kita asumsikan bahwa itu disimpan dalam RAM:
0x00010004: 0x00000004
Bagian pertama adalah alamat, bagian kedua adalah nilai. Ketika program Anda (yang dijalankan sebagai kode mesin) berjalan, yang dilihatnya 0x00010004
hanyalah nilainya 0x000000004
. Itu tidak 'tahu' jenis data ini, dan tidak tahu bagaimana 'seharusnya' digunakan.
Jadi, bagaimana program Anda mengetahui hal yang benar untuk dilakukan? Pertimbangkan kode ini:
int x = 4;
x = x + 5;
Kami telah membaca dan menulis di sini. Ketika program Anda membaca x
dari memori, ia menemukan di 0x00000004
sana. Dan program Anda tahu untuk menambahkannya 0x00000005
. Dan alasan program Anda 'tahu' ini adalah operasi yang valid, karena kompiler memastikan bahwa operasi itu valid melalui tipe-safety. Kompiler Anda telah memverifikasi bahwa Anda dapat menambahkan 4
dan 5
bersama - sama. Jadi ketika kode biner Anda berjalan (exe), itu tidak harus melakukan verifikasi itu. Itu hanya mengeksekusi setiap langkah secara membabi buta, dengan asumsi semuanya baik-baik saja (hal-hal buruk terjadi ketika mereka sebenarnya, bukan OK).
Cara lain untuk memikirkannya adalah seperti ini. Saya memberi Anda informasi ini:
0x00000004: 0x12345678
Format yang sama seperti sebelumnya - alamat di sebelah kiri, nilai di sebelah kanan. Jenis apa nilainya? Pada titik ini, Anda tahu sebanyak mungkin informasi tentang nilai itu seperti halnya komputer Anda saat menjalankan kode. Jika saya mengatakan kepada Anda untuk menambahkan 12743 ke nilai itu, Anda bisa melakukannya. Anda tidak tahu apa akibat dari operasi itu pada keseluruhan sistem, tetapi menambahkan dua angka adalah sesuatu yang benar-benar Anda kuasai, sehingga Anda bisa melakukannya. Apakah itu membuat nilai menjadi int
? Tidak harus - Yang Anda lihat adalah dua nilai 32-bit dan operator tambahan.
Mungkin beberapa kebingungan kemudian mendapatkan kembali data. Jika kita memiliki:
char A = 'a';
Bagaimana komputer tahu untuk ditampilkan a
di konsol? Ya, ada banyak langkah untuk itu. Yang pertama adalah pergi ke A
lokasi di memori dan membacanya:
0x00000004: 0x00000061
Nilai hex untuk a
di ASCII adalah 0x61, jadi di atas mungkin sesuatu yang akan Anda lihat di memori. Jadi sekarang kode mesin kami tahu nilai integer. Bagaimana cara mengetahui nilai integer menjadi karakter untuk menampilkannya? Sederhananya, kompiler memastikan untuk memasukkan semua langkah yang diperlukan untuk melakukan transisi itu. Tetapi komputer Anda sendiri (atau program / exe) tidak tahu apa tipe data itu. Nilai 32-bit itu bisa berupa apa saja - int
,, char
setengah dari double
, pointer, bagian dari array, bagian dari string
, bagian dari instruksi, dll.
Berikut adalah interaksi singkat yang mungkin dimiliki program Anda (exe) dengan komputer / sistem operasi.
Program: Saya ingin memulai. Saya membutuhkan memori 20 MB.
Sistem Operasi: menemukan 20 MB memori gratis yang tidak digunakan dan menyerahkannya
(Catatan penting adalah bahwa ini bisa kembali setiap 20 MB memori, mereka bahkan tidak harus berdekatan. Pada titik ini, program ini sekarang dapat beroperasi dalam memori itu tanpa berbicara dengan OS)
Program: Saya akan berasumsi bahwa tempat pertama dalam memori adalah variabel integer 32-bit x
.
(Kompiler memastikan bahwa akses ke variabel lain tidak akan pernah menyentuh tempat ini dalam memori. Tidak ada pada sistem yang mengatakan byte pertama adalah variabel x
, atau variabel itu x
adalah bilangan bulat. Analogi: Anda memiliki tas. Anda memberi tahu orang-orang bahwa Anda hanya akan memasukkan bola berwarna kuning ke dalam tas ini. Ketika seseorang kemudian menarik sesuatu keluar dari tas, maka akan mengejutkan bahwa mereka akan mengeluarkan sesuatu yang berwarna biru atau kubus - sesuatu yang sangat salah terjadi. Hal yang sama berlaku untuk komputer: Anda: Program sekarang mengasumsikan tempat memori pertama adalah variabel x dan itu adalah bilangan bulat.Jika sesuatu yang lain pernah ditulis di atas byte memori ini atau diasumsikan sebagai sesuatu yang lain - sesuatu yang mengerikan telah terjadi.Kompiler memastikan hal-hal semacam ini tidak akan terjadi)
Program: Sekarang saya akan menulis 2
ke empat byte pertama di mana saya berasumsi x
berada di.
Program: Saya ingin menambahkan 5 x
.
Membaca nilai X menjadi register sementara
Menambahkan 5 ke register sementara
Menyimpan nilai register sementara kembali ke byte pertama, yang masih dianggap x
.
Program: Saya akan menganggap byte yang tersedia berikutnya adalah variabel char y
.
Program: Saya akan menulis a
ke variabel y
.
Program: Saya ingin menampilkan konten y
Membaca nilai di tempat memori kedua
Menggunakan perpustakaan untuk mengkonversi dari byte ke karakter
Menggunakan pustaka grafis untuk mengubah layar konsol (mengatur piksel dari hitam ke putih, menggulir satu baris, dll)
(Dan itu berlanjut dari sini)
Yang mungkin membuat Anda terpaku adalah - apa yang terjadi ketika titik pertama dalam ingatan tidak lagi x
? atau yang kedua tidak lagi y
? Apa yang terjadi ketika seseorang membaca x
sebagai char
atau y
sebagai penunjuk? Singkatnya, hal-hal buruk terjadi. Beberapa dari hal-hal ini memiliki perilaku yang jelas, dan beberapa memiliki perilaku yang tidak terdefinisi. Perilaku yang tidak terdefinisi adalah persis seperti itu - apa pun dapat terjadi, mulai dari tidak ada sama sekali, hingga crash program atau sistem operasi. Bahkan perilaku yang didefinisikan dengan baik bisa berbahaya. Jika saya dapat mengubah x
menjadi pointer ke program saya, dan membuat program Anda menggunakannya sebagai pointer, maka saya bisa membuat program Anda untuk mulai menjalankan program saya - yang persis seperti yang dilakukan peretas. Kompiler ada untuk membantu memastikan kita tidak menggunakan int x
sebagaistring
, dan hal-hal semacam itu. Kode mesin itu sendiri tidak mengetahui tipe, dan hanya akan melakukan apa yang diperintahkan oleh instruksi. Ada juga sejumlah besar informasi yang ditemukan pada saat run-time: byte memori manakah yang diperbolehkan untuk digunakan oleh program? Apakah x
dimulai pada byte pertama atau ke-12?
Tetapi Anda dapat membayangkan betapa mengerikannya menulis program seperti ini (dan Anda bisa, dalam bahasa majelis). Anda memulai dengan 'mendeklarasikan' variabel Anda - Anda memberi tahu diri sendiri bahwa byte 1 adalah x
, byte 2 adalah y
, dan saat Anda menulis setiap baris kode, memuat dan menyimpan register, Anda (sebagai manusia) harus mengingat yang mana x
dan mana satu y
, karena sistem tidak tahu. Dan Anda (sebagai manusia) harus mengingat tipe x
dan y
apa, karena sekali lagi - sistem tidak tahu.