Mengapa executable bergantung pada OS tetapi tidak pada CPU?

16

Jika saya menulis program C dan mengkompilasinya ke .exefile, .exefile tersebut berisi instruksi mesin mentah ke CPU. (Kupikir).

Jika demikian, bagaimana mungkin bagi saya untuk menjalankan file yang dikompilasi di komputer yang menjalankan versi Windows modern? Setiap keluarga CPU memiliki set instruksi yang berbeda. Jadi bagaimana mungkin komputer yang menjalankan OS yang sesuai dapat memahami instruksi dalam .exefile saya , terlepas dari CPU fisiknya?

Juga, sering di situs web di halaman "unduh" pada beberapa aplikasi, Anda memiliki unduhan untuk Windows, untuk Linux, dan untuk Mac (seringkali dua unduhan untuk setiap OS, untuk komputer 86 dan 64 bit). Mengapa tidak ada lebih banyak unduhan, untuk setiap keluarga CPU?

Aviv Cohn
sumber
4
CPU memiliki standar seperti x86, 64b, dll. Executable DO tergantung pada CPU. Anda tidak dapat menjalankan exe yang Anda sebutkan pada beberapa CPU khusus seperti RISC, ada banyak CPU tujuan khusus juga
InformedA
OS terdiri dari executable, dan mereka bergantung pada CPU, bukan pada OS, karena mereka adalah OS.
Tulains Córdova
Karena kompatibilitas ke belakang.
MiKL
2
sering dua unduhan untuk setiap OS, untuk komputer 86 dan 64 bit : Saya menafsirkannya sebagai ketergantungan executable pada CPU.
mouviciel

Jawaban:

37

Executables tergantung pada OS dan CPU:

  • Set Instruksi: Instruksi biner dalam executable didekodekan oleh CPU berdasarkan beberapa set instruksi. Sebagian besar CPU konsumen mendukung set instruksi x86 ("32bit") dan / atau AMD64 ("64bit"). Suatu program dapat dikompilasi untuk salah satu dari set instruksi ini, tetapi tidak keduanya. Ada ekstensi untuk set instruksi ini; dukungan untuk ini dapat ditanyakan saat runtime. Ekstensi semacam itu menawarkan dukungan SIMD, misalnya. Mengoptimalkan kompiler dapat mencoba memanfaatkan ekstensi ini jika ada, tetapi biasanya juga menawarkan jalur kode yang berfungsi tanpa ekstensi apa pun.

  • Binary Format: Eksekusi harus sesuai dengan format biner tertentu, yang memungkinkan sistem operasi memuat, menginisialisasi, dan memulai program dengan benar. Windows terutama menggunakan format Portable Executable, sedangkan Linux menggunakan ELF.

  • API Sistem: Program ini mungkin menggunakan pustaka, yang harus ada pada sistem pelaksana. Jika suatu program menggunakan fungsi dari Windows API, itu tidak dapat dijalankan di Linux. Di dunia Unix, API sistem operasi pusat telah distandarisasi untuk POSIX: program yang hanya menggunakan fungsi POSIX akan dapat dijalankan pada sistem Unix yang sesuai, seperti Mac OS X dan Solaris.

Jadi jika dua sistem menawarkan API dan pustaka sistem yang sama, jalankan pada set instruksi yang sama, dan gunakan format biner yang sama, maka sebuah program yang dikompilasi untuk satu sistem juga akan berjalan pada yang lain.

Namun, ada beberapa cara untuk mencapai lebih banyak kompatibilitas:

  • Sistem yang berjalan pada set instruksi AMD64 umumnya juga akan menjalankan executable x86. Format biner menunjukkan mode mana yang harus dijalankan. Menangani program 32bit dan 64bit memerlukan upaya tambahan dari sistem operasi.

  • Beberapa format biner memungkinkan file berisi beberapa versi program, dikompilasi untuk set instruksi yang berbeda. "Binari gemuk" seperti itu didorong oleh Apple saat mereka beralih dari arsitektur PowerPC ke x86.

  • Beberapa program tidak dikompilasi ke kode mesin, tetapi ke beberapa representasi perantara. Ini kemudian diterjemahkan dengan cepat ke instruksi aktual, atau mungkin ditafsirkan. Ini membuat program independen dari arsitektur spesifik. Strategi seperti itu digunakan pada UCSD p-System.

  • Satu sistem operasi dapat mendukung berbagai format biner. Windows cukup kompatibel ke belakang dan masih mendukung format dari era DOS. Di Linux, Wine memungkinkan format Windows untuk dimuat.

  • API satu sistem operasi dapat diterapkan kembali untuk OS host lain. Pada Windows, Cygwin dan subsistem POSIX dapat digunakan untuk mendapatkan (kebanyakan) lingkungan yang sesuai dengan POSIX. Di Linux, Wine menambah banyak API Windows.

  • Pustaka lintas-platform memungkinkan program untuk independen dari OS API. Banyak bahasa pemrograman memiliki pustaka standar yang mencoba untuk mencapai hal ini, misalnya Java dan C.

  • Sebuah emulator mensimulasikan sistem yang berbeda dengan parsing format biner asing, menafsirkan petunjuk, dan menawarkan implementasi ulang dari semua API yang diperlukan. Emulator biasanya digunakan untuk menjalankan game Nitendo lama di PC modern.

amon
sumber
10
Anda harus menyebutkan bahwa kedua java dan .net adalah contoh dari menggunakan format perantara - format perantara sangat populer saat ini, dan bukan hanya peninggalan sistem tahun 1970-an yang lari dari 5 1/4 disket.
jmoreno
@AKoscianski terima kasih atas hasil edit yang Anda sarankan . Namun, saya pikir desain keamanan bukan alasan mengapa executable bergantung pada OS, tetapi alasan mengapa kita memiliki pemisahan OS vs userland. Berbagai API untuk fungsionalitas sistem operasi yang dilindungi tersebut telah ditangani oleh bagian "Sistem API" dari jawaban ini.
amon
2

99% PC saat ini yang menjalankan Windows memiliki prosesor 64 bit, yang juga mampu menjalankan perangkat lunak 32 bit. Satu persen lainnya memiliki prosesor 32 bit. Jadi perangkat lunak yang dibangun untuk prosesor 32 bit berjalan di mana-mana. Perangkat lunak yang dibangun untuk prosesor 64 bit berjalan pada setiap PC yang menjadi perhatian pembuat perangkat lunak.

MacOS X dan iOS mendukung "fat binaries" - apa yang Anda unduh sebenarnya dapat berisi versi untuk prosesor yang berbeda. Tidak ada yang membangun aplikasi untuk prosesor PowerPC lagi, tetapi pada beberapa titik beberapa tahun yang lalu sebuah executable dapat berisi PowerPC, Intel 32 bit, dan versi Intel 64 bit, dan yang tepat akan dieksekusi. Di iOS saat ini, ketika Anda mengunduh aplikasi, Anda akan mendapatkan versi yang sesuai untuk prosesor di perangkat Anda. Unduh di perangkat yang berbeda, dan Anda mendapatkan versi yang berbeda. Sama sekali tidak terlihat oleh pengguna.

gnasher729
sumber
-1

Exe berisi informasi lebih dari sekadar kode mesin mentah. OS membaca ini ketika memuatnya dan dapat mengetahui bagaimana seharusnya dijalankan.

Ketika Anda mengkompilasi Anda umumnya menetapkan target CPU, jika Anda tidak kompiler akan memilih CPU Anda saat ini dan akan membatasi diri untuk hanya memilih instruksi yang umum untuk CPU Anda dan versi yang lebih lama. Jika Anda ingin menggunakan instruksi baru yang mewah yang khusus untuk revisi tertentu dari target CPU Anda, Anda bisa memberi tahu kompiler atau secara manual kode itu dengan baik kode intrinsik atau inline assembly. Namun program Anda akan macet jika dijalankan pada CPU yang tidak mendukung instruksi itu.

James
sumber