Bagaimana jalur kode dieksekusi oleh CPU?

11

Saya mencoba untuk benar-benar memahami bagaimana sebenarnya bahasa tingkat tinggi dikonversi menjadi kode mesin dan kemudian dieksekusi oleh cpu.

Saya mengerti bahwa kode tersebut dikompilasi ke dalam kode mesin, yang merupakan kode tingkat rendah yang dapat digunakan CPU. Jika saya memiliki pernyataan tugas, katakan:

x = x + 5;
y = x - 3;

Apakah CPU menjalankan setiap baris satu per satu? Jadi pertama-tama akan menjalankan x = x + 5; instruksi dan instruksi selanjutnya yang akan dilakukan CPU adalah y = x-3; Saya benar-benar mencoba memahami proses eksekusi dan bagaimana kode yang saya tulis sebenarnya dieksekusi oleh CPU.

Frankie
sumber
Anda mungkin ingin mencoba memahami desain salah satu CPU open source, ada beberapa implementasi berbasis stack yang sangat sederhana seperti excamera.com/sphinx/fpga-j1.html - mereka jauh lebih sederhana daripada arsitektur 3-address seperti dalam contoh Anda.
SK-logic
3
Ketika saya masuk ke bisnis ini, ini akan memiliki jawaban yang sederhana dan jelas. Saat ini, CPU sangat rumit dan melakukan segala macam hal untuk meningkatkan daya pemrosesan.
David Thornley

Jawaban:

12

Baris kode tidak ada hubungannya dengan bagaimana CPU mengeksekusinya. Saya sarankan membaca assembler, karena itu akan mengajarkan Anda banyak tentang bagaimana sebenarnya perangkat keras melakukan sesuatu. Anda juga bisa mendapatkan output assembler dari banyak kompiler.

Kode itu dapat dikompilasi menjadi sesuatu seperti (dalam bahasa assembly yang dibuat-buat):

load R1, [x] ; meaning load the data stored at memory location x into register 1
add R1, 5
store [x], R1 ; store the modified value into the memory location x
sub R1, 3
store R1, [y]

Namun, jika kompiler tahu bahwa variabel tidak digunakan lagi, operasi toko mungkin tidak dipancarkan.

Sekarang bagi debugger untuk mengetahui kode mesin apa yang sesuai dengan satu baris sumber program, anotasi ditambahkan oleh kompiler untuk menunjukkan baris mana yang sesuai dengan di mana dalam kode mesin.

maxpolun
sumber
Kenapa tidak? Arsitektur 3-alamat akan memiliki instruksi seperti ADD Rx, Rx, $5dan SUB Ry, Rx, $3(dengan asumsi bahwa variabel x dan y telah dipetakan ke dalam register). Anda sedang mendeskripsikan pendekatan RISC load / store.
SK-logic
1
@ SK-logic: Walaupun hal itu dapat terjadi pada baris kode yang sangat sederhana dalam bahasa pemrograman yang sangat sederhana dengan tipe data dan operasi yang didukung CPU dengan cukup baik, ini tidak menjadi masalah umum. Sangat mudah bagi para ahli, tetapi pertama-tama penting untuk menyadari instruksi kode mesin umumnya menanggung resemablence kecil ke baris kode dalam lanugage tingkat tinggi.
@ SK-Logika: yang hanya berfungsi untuk contoh khusus ini. Secara umum, bagaimanapun, maxpolun benar. Pernyataan bahasa tingkat tinggi harus diterjemahkan ke bahasa tingkat yang lebih rendah, dengan lebih banyak "birokrasi" diperlukan untuk melakukan hal-hal yang secara konsep sederhana. Saya kira OP meminta contoh transformasi ini.
Andres F.
1
@ SK-Logic: OP memulai pertanyaannya dengan "Saya mencoba untuk benar-benar memahami bagaimana sebenarnya bahasa tingkat tinggi [...]"
Andres F.
1
@ SK-logic Konteksnya adalah "Jika saya memiliki pernyataan tugas yang mengatakan: [potongan kode] Apakah CPU mengeksekusi setiap baris satu per satu?" - Menurut saya itu dimaksudkan untuk menjadi kode sumber dalam bahasa non-assembler. Secara umum, saya tidak melihat indikator pemahaman tentang bagaimana kode mesin tingkat rendah, dan beberapa ungkapan (seperti berbicara tentang baris) menunjukkan beberapa kesalahpahaman. Itu tidak mustahil seperti yang Anda maksudkan, tidak semua orang merasa senang menjadi yang pertama dilemparkan ke beberapa mikrokontroler sederhana (seperti saya dan yang lainnya). Mungkin Frankie harus menjelaskan.
2

Tergantung.

Pada hari-hari awal mesin yang sangat sederhana, ya, kode dieksekusi satu baris pada satu waktu. Ketika mesin menjadi lebih besar, lebih cepat, dan lebih kompleks, Anda mulai melihat kemampuan untuk menjalankan beberapa instruksi secara bersamaan dan memori membaca dan menulis membutuhkan waktu lebih lama daripada operasi pada register.

Mengoptimalkan kompiler harus mempertimbangkan hal ini, dan baris yang Anda berikan dapat dieksekusi "lebih atau kurang" secara paralel, dengan satu bagian prosesor bekerja pada perhitungan y, sementara bagian lain menyimpan nilai baru yang sebelumnya dihitung dari x (dan perhitungan y menggunakan nilai baru dari register).

Control Data 6600 adalah mesin pertama yang saya tahu melakukan hal-hal semacam ini. Selain integer mengambil 300 nsec, referensi memori (baca atau tulis) mengambil 1000 nsec, mengalikan dan membagi membutuhkan BANYAK lebih lama. Hingga sekitar sepuluh instruksi semuanya dapat dieksekusi secara paralel, tergantung pada unit fungsional mana yang diperlukan. Kompiler FORTRAN CDC 6600 SANGAT bagus dalam menjadwalkan semua ini.

John R. Strohm
sumber
Dalam hal ini input dari instruksi selanjutnya tergantung pada hasil instruksi pertama, sehingga harus dieksekusi secara berurutan.
SK-logic
@ SK-logic: Tidak cukup. Input dari baris kedua tergantung pada hasil dari sisi kanan dari baris pertama, tetapi, hanya berdasarkan apa yang dapat kita lihat dalam kode contoh asli, itu mungkin TIDAK tergantung pada penyimpanan ke memori hasil dari baris pertama. Jika x telah dinyatakan volatile (dalam C / C ++), maka kompiler akan diminta untuk menyimpan hasilnya terlebih dahulu, DAN LALU BANTU ITU DARI MEMORY, sebelum mulai menghitung nilai baru y, karena "volatile" berarti sesuatu (handler interrupt, katakanlah) bisa masuk dan zap x antara dua baris.
John R. Strohm
Saya berasumsi x dan y adalah register (dan kodenya dalam bahasa pseudoassembly 3-address daripada sesuatu seperti C). Dalam hal ini kedua instruksi tidak dapat dihindari berurutan. Kalau tidak, OP harus mengajukan dua atau lebih pertanyaan yang berbeda, bukan yang ini.
SK-logic
Saya bertanya-tanya apakah prosesor akan mencoba untuk "berspekulasi" apa nilainya x? Dengan cara ini, kode sudah dieksekusi dan disimpan dalam cache.
Ngarai Kolob
Bahkan jika mereka register, BERGANTUNG PADA MESIN, Anda tidak dapat berasumsi bahwa instruksi mengeksekusi sepenuhnya secara berurutan. The 6600 memiliki logika penjadwalan ("papan skor") yang akan memaksa semantik berurutan, berdasarkan pada asumsi bahwa programmer ingin melakukan yang jelas. Kemudian mesin menghapus perangkat keras itu, alih-alih mengandalkan kompiler untuk menjadwalkan instruksi dengan hati-hati. Pemrogram manusia yang melakukan pemrograman bahasa rakitan pada binatang buas itu AKAN SENDIRI.
John R. Strohm
1

Tidak, tidak ada pemetaan satu-ke-satu antara baris kode / instruksi dalam bahasa tingkat tinggi dan rendah. Bahkan, kedua baris di atas diterjemahkan ke dalam beberapa instruksi kode mesin , seperti

  1. memuat nilai dari alamat memori tertentu ke dalam register
  2. ubah nilainya
  3. tulis kembali ke memori

Detail sebenarnya dari instruksi ini bervariasi antar platform.

Ini adalah pandangan dasar dari banyak hal. Namun, untuk lebih memperumit masalah, CPU modern menerapkan teknik seperti pipa eksekusi , eksekusi out-of-order dan beberapa core , antara lain. Ini menghasilkan CPU melakukan banyak hal sekaligus, misal pipeline memproses fase berbeda dari instruksi selanjutnya secara paralel dalam unit pemrosesan yang sama, sementara banyak core dapat memproses instruksi independen secara paralel.

Péter Török
sumber
0

Anda harus melihat dengan sangat rinci dalam sebuah buku untuk menemukan lebih banyak detail tentang cara kerjanya, mungkin juga kelas kompiler.

Pada dasarnya, pertanyaan Anda berfokus pada 2 aspek berbeda.

1) Bagaimana kode diterjemahkan ke dalam kode mesin?

2) Kapan / bagaimana kode dihitung menggunakan paralelisasi?

Jawaban untuk 1) tergantung pada bahasa yang Anda gunakan (meskipun untuk contoh Anda sepele sehingga hasilnya akan sama). Cara kompiler melakukan terjemahan ke kode mesin adalah salah satu kekuatan bahasa. Selain itu, ada beberapa masalah yang perlu dipertimbangkan dalam contoh Anda, kode harus memuat data ke dalam memori, menyimpannya, dll.

Akhirnya paralelisasi adalah fitur yang dapat Anda paksa dari sudut pandang pemrograman, tetapi secara singkat, beberapa prosesor mungkin mencoba untuk berpikir bahwa beberapa bagian dari kode dapat dijalankan pada saat yang sama, karena mereka independen. Dalam kasus Anda, jelas, ini bukan masalahnya, karena Anda perlu menjalankan pernyataan secara berurutan, jadi tidak, itu tidak akan berjalan pada saat yang sama.

SRKX
sumber