Saya bingung tentang kode mesin dan kode asli dalam konteks bahasa .NET.
Apa perbedaan di antara keduanya? Apakah mereka sama?
Saya bingung tentang kode mesin dan kode asli dalam konteks bahasa .NET.
Apa perbedaan di antara keduanya? Apakah mereka sama?
Jawaban:
Istilah tersebut memang agak membingungkan, karena terkadang digunakan secara tidak konsisten.
Kode mesin: Ini yang paling jelas. Ini adalah kode yang menggunakan instruksi kode byte yang dipahami dan dijalankan oleh prosesor Anda (bagian fisik logam yang sebenarnya). Semua kode lainnya harus diterjemahkan atau diubah menjadi kode mesin sebelum mesin Anda dapat menjalankannya.
Kode asli: Istilah ini terkadang digunakan di tempat-tempat di mana kode mesin (lihat di atas) dimaksudkan. Namun, terkadang juga digunakan untuk mengartikan kode yang tidak terkelola (lihat di bawah).
Kode unmanaged dan kode dikelola: unmanaged code mengacu pada kode yang ditulis dalam bahasa pemrograman seperti C atau C ++, yang dikompilasi langsung ke kode mesin . Ini kontras dengan kode yang dikelola , yang ditulis dalam C #, VB.NET, Java, atau serupa, dan dieksekusi dalam lingkungan virtual (seperti .NET atau JavaVM) yang "mensimulasikan" prosesor dalam perangkat lunak. Perbedaan utamanya adalah kode terkelola "mengelola" sumber daya (sebagian besar alokasi memori) untuk Anda dengan menggunakan pengumpulan sampah dan dengan menjaga referensi ke objek tetap buram. Kode tidak terkelolaadalah jenis kode yang mengharuskan Anda mengalokasikan dan mengalokasikan memori secara manual, terkadang menyebabkan kebocoran memori (saat Anda lupa mengalokasikannya) dan terkadang kesalahan segmentasi (saat Anda membatalkan alokasi terlalu cepat). Tidak terkelola juga biasanya menyiratkan tidak ada pemeriksaan run-time untuk kesalahan umum seperti dereferensi penunjuk nol atau luapan batas array.
Sebenarnya, sebagian besar bahasa yang diketik secara dinamis - seperti Perl, Python, PHP dan Ruby - juga merupakan kode yang dikelola . Namun, mereka tidak secara umum dijelaskan seperti itu, yang menunjukkan bahwa kode terkelola sebenarnya merupakan istilah pemasaran untuk lingkungan pemrograman komersial yang sangat besar, serius, dan komersial (.NET dan Java).
Kode perakitan: Istilah ini umumnya mengacu pada jenis kode sumber yang ditulis orang ketika mereka benar-benar ingin menulis kode byte. Sebuah assembler adalah program yang mengubah kode sumber ini menjadi nyata byte-code. Ini bukan kompilator karena transformasinya 1-ke-1. Namun, istilah ini ambigu mengenai jenis kode byte yang digunakan: dapat dikelola atau tidak. Jika tidak dikelola, kode byte yang dihasilkan adalah kode mesin . Jika dikelola, ini menghasilkan kode byte yang digunakan di belakang layar oleh lingkungan virtual seperti .NET. Kode yang dikelola (misalnya C #, Java) dikompilasi ke dalam bahasa kode byte khusus ini, yang dalam kasus .NET disebut Common Intermediate Language (CIL) dan di Jawa disebut kode byte Java. Biasanya ada sedikit kebutuhan bagi programmer umum untuk mengakses kode ini atau menulis dalam bahasa ini secara langsung, tetapi ketika orang melakukannya, mereka sering menyebutnya sebagai kode assembly karena mereka menggunakan assembler untuk mengubahnya menjadi kode byte.
Apa yang Anda lihat saat Anda menggunakan Debug + Windows + Disassembly saat men-debug program C # adalah panduan yang baik untuk istilah-istilah ini. Berikut adalah versi yang dianotasi ketika saya menyusun program 'hello world' yang ditulis dalam C # dalam konfigurasi Rilis dengan pengoptimalan JIT diaktifkan:
static void Main(string[] args) {
Console.WriteLine("Hello world");
00000000 55 push ebp ; save stack frame pointer
00000001 8B EC mov ebp,esp ; setup current frame
00000003 E8 30 BE 03 6F call 6F03BE38 ; Console.Out property getter
00000008 8B C8 mov ecx,eax ; setup "this"
0000000a 8B 15 88 20 BD 02 mov edx,dword ptr ds:[02BD2088h] ; arg = "Hello world"
00000010 8B 01 mov eax,dword ptr [ecx] ; TextWriter reference
00000012 FF 90 D8 00 00 00 call dword ptr [eax+000000D8h] ; TextWriter.WriteLine()
00000018 5D pop ebp ; restore stack frame pointer
}
00000019 C3 ret ; done, return
Klik kanan jendela dan centang "Show Code Bytes" untuk mendapatkan tampilan serupa.
Kolom di sebelah kiri adalah alamat kode mesin. Nilainya dipalsukan oleh debugger, kodenya sebenarnya terletak di tempat lain. Tapi itu bisa di mana saja, tergantung pada lokasi yang dipilih oleh compiler JIT, jadi debugger mulai menomori alamat dari 0 pada awal metode.
Kolom kedua adalah kode mesin . Angka 1 dan 0 aktual yang dijalankan CPU. Kode mesin, seperti di sini, biasanya ditampilkan dalam hex. Ilustratif mungkin adalah bahwa 0x8B memilih instruksi MOV, byte tambahan yang ada untuk memberi tahu CPU dengan tepat apa yang perlu dipindahkan. Perhatikan juga dua jenis instruksi CALL, 0xE8 adalah panggilan langsung, 0xFF adalah instruksi panggilan tidak langsung.
Kolom ketiga adalah kode assembly . Perakitan adalah bahasa sederhana, dirancang untuk memudahkan penulisan kode mesin. Ini dibandingkan dengan C # yang dikompilasi ke IL. Kompiler yang digunakan untuk menerjemahkan kode assembly disebut "assembler". Anda mungkin memiliki Microsoft assembler di komputer Anda, nama yang dapat dieksekusi adalah ml.exe, ml64.exe untuk versi 64-bit. Ada dua versi umum bahasa assembly yang digunakan. Yang Anda lihat adalah yang digunakan Intel dan AMD. Di dunia open source, perakitan dalam notasi AT&T adalah hal biasa. Sintaks bahasa sangat bergantung pada jenis CPU yang dibuat, bahasa assembly untuk PowerPC sangat berbeda.
Oke, itu menangani dua istilah dalam pertanyaan Anda. "Kode asli" adalah istilah fuzzy, ini tidak jarang digunakan untuk mendeskripsikan kode dalam bahasa yang tidak terkelola. Mungkin instruktif adalah untuk melihat jenis kode mesin apa yang dihasilkan oleh kompilator C. Ini adalah versi 'hello world' di C:
int _tmain(int argc, _TCHAR* argv[])
{
00401010 55 push ebp
00401011 8B EC mov ebp,esp
printf("Hello world");
00401013 68 6C 6C 45 00 push offset ___xt_z+128h (456C6Ch)
00401018 E8 13 00 00 00 call printf (401030h)
0040101D 83 C4 04 add esp,4
return 0;
00401020 33 C0 xor eax,eax
}
00401022 5D pop ebp
00401023 C3 ret
Saya tidak memberi anotasi, terutama karena sangat mirip dengan kode mesin yang dihasilkan oleh program C #. Pemanggilan fungsi printf () sangat berbeda dari pemanggilan Console.WriteLine () tetapi yang lainnya hampir sama. Juga perhatikan bahwa debugger sekarang membuat alamat kode mesin yang sebenarnya dan itu sedikit lebih pintar tentang simbol. Efek samping dari membuat info debug setelah membuat kode mesin seperti yang sering dilakukan oleh kompiler yang tidak dikelola. Saya juga harus menyebutkan bahwa saya mematikan beberapa opsi pengoptimalan kode mesin untuk membuat kode mesin terlihat serupa. Kompiler C / C ++ memiliki lebih banyak waktu yang tersedia untuk mengoptimalkan kode, seringkali hasilnya sulit untuk ditafsirkan. Dan sangat sulit untuk di-debug.
Poin utama di sini adalah ada sangat sedikit perbedaan antara kode mesin yang dihasilkan dari bahasa yang dikelola oleh kompilator JIT dan kode mesin yang dihasilkan oleh kompilator kode asli. Yang merupakan alasan utama mengapa bahasa C # dapat bersaing dengan kompilator kode asli. Satu-satunya perbedaan nyata di antara mereka adalah panggilan fungsi dukungan. Banyak di antaranya diimplementasikan di CLR. Dan yang utama berputar di sekitar pengumpul sampah.
Kode asli dan kode mesin adalah hal yang sama - byte sebenarnya yang dieksekusi oleh CPU.
Kode assembly memiliki dua arti: satu adalah kode mesin yang diterjemahkan ke dalam bentuk yang lebih dapat dibaca manusia (dengan byte untuk instruksi yang diterjemahkan menjadi mnemonik pendek mirip kata seperti "JMP" (yang "melompat" ke tempat lain dalam kode). Yang lainnya adalah bytecode IL (byte instruksi yang dihasilkan oleh kompiler seperti C # atau VB, yang pada akhirnya akan diterjemahkan ke dalam kode mesin, tetapi belum) yang hidup dalam DLL atau EXE.
Dalam .NET, majelis berisi kode MS Intermediate Language (MSIL, terkadang CIL).
Ini seperti kode mesin 'tingkat tinggi'.
Saat dimuat, MSIL dikompilasi oleh kompiler JIT menjadi kode asli (kode mesin Intel x86 atau x64).