Apakah ada perbedaan nyata antara kompiler dan assembler?

14

Apakah ada perbedaan di antara keduanya? Sesuai dengan buku Ullman , kompiler mengonversi satu bahasa ke bahasa lain (biasanya tingkat rendah), dan begitu juga assembler. Bagaimana keduanya berbeda?

gpuguy
sumber
1
Assembler adalah kompiler yang melakukan serangkaian tugas tertentu. Istilah-istilah tersebut agak berbeda dalam praktiknya, tetapi definisi dasar "kompiler" (menerjemahkan antar bahasa) berlaku.
Raphael
Semua assembler adalah kompiler (sederhana), karena mereka mengubah satu bahasa ke bahasa lain. Tidak semua kompiler adalah assembler.
user253751

Jawaban:

16

Assembler menerjemahkan kode assembly ke kode mesin. Terjemahan bersifat mekanis, dan dapat dilakukan hanya dengan satu cara. Sebaliknya, kompiler memiliki lebih banyak kebebasan ketika mengkompilasi bahasa pemrograman yang relevan - ia dapat mengoptimalkan, misalnya, dan bahkan kompiler yang tidak mengoptimalkan menghasilkan kode yang berbeda. Juga, kompiler dapat ditulis dengan cara yang memisahkan "front-end" (sesuai dengan bahasa pemrograman) dan "back-end" (sesuai dengan arsitektur komputer), sedangkan dengan assembler keduanya selalu sama.

Yuval Filmus
sumber
2
Mengapa terjemahan hanya bisa dilakukan dengan satu cara? Apakah itu berarti bahwa kode asm yang berasal tidak dapat dihasilkan untuk kode mesin yang diberikan (dan arsitektur target)? Kedengarannya kontra intuitif bagi saya. Karena jika instruksi kode mesin yang diberikan dapat memetakan ke beberapa instruksi asm, lalu bagaimana mesin memutuskan instruksi mana yang akan dieksekusi? Apakah saya melewatkan sesuatu?
Utku
2
SEBUAHT(SEBUAH)SEBUAH
Terima kasih, saya juga melihat bahwa dalam buku Ullman, kompiler memiliki ujung depan dan backend. Jika saya benar, backend melakukan optimasi dalam bahasa perantara, pembuatan kode mesin, dan optimisasi kode mesin, dan masing-masing dari tiga tugas dapat dilakukan dalam lebih dari satu cara. Apakah bagian "backend" adalah assembler? Apakah bahasa perantara merupakan bahasa rakitan? Saya kira ya, tetapi jawaban Anda menyebutkan bahwa assembler melakukan tugasnya hanya dalam satu cara.
Tim
Saya mempostingnya di sini cs.stackexchange.com/questions/98854/...
Tim
Bahasa perantara biasanya mengacu pada bahasa yang independen terhadap mesin.
Yuval Filmus
11

Intinya adalah bahwa menulis kompiler lebih menyenangkan daripada assembler. Bahasa assembly biasanya dirancang hampir sepele untuk parse dan ketik cek dan cenderung melibatkan banyak generator yang digerakkan oleh tabel ("opcode untuk add adalah 01110", "untuk instruksi pemuatan register operan tujuan ditentukan oleh bit 17 hingga 21). "). Biasanya bagian yang paling menarik dari assembler adalah bagian yang menyelesaikan label simbolik menjadi angka.

Namun , sebagian besar perakit dapat melakukan sejumlah kecil aritmatika (menambahkan label simbolik dengan konstanta kecil, misalnya) dan sebagian besar perakit baik memiliki atau terintegrasi dengan fasilitas pemrosesan makro. (Pada sebagian besar sistem Unix, fitur makro sebenarnya disediakan dengan menjalankan pra-prosesor C di atas unit sebelum meneruskannya ke assembler.)

Assembler MIPS harus melangkah lebih jauh dari itu dan membuat beberapa keputusan pembuatan kode yang menarik dan melakukan sedikit optimasi. Bahasa mesin MIPS memerlukan urutan kode yang berbeda untuk memuat konstanta yang berbeda, misalnya, dan karenanya assembler harus memilih urutan kode setelah membangun konstanta . Lebih lanjut, kode mesin MIPS memiliki konsep slot keterlambatan , tetapi merupakan tanggung jawab assembler untuk mengabstraksikan ini dan menyajikan bahasa assembly abstrak yang lebih "normal" ke kompiler. Jadi assembler MIPS perlu melakukan beberapa penjadwalan instruksi lokal.

Perbedaan ini semakin kabur oleh beberapa karya Norman Ramsey , khususnya bahasa rakitan C- portable-nya. (Makalah yang relevan adalah Ramsey dan Peyton Jones, "Bahasa Menengah Tunggal yang Mendukung Berbagai Implementasi Pengecualian", Prog. Lang. Impl. Dan Dsgn. , (PLDI-21): 285–298, 2000. ) Dan akhirnya, ada juga merupakan Typed Assembly Language dari David Walker dan Greg Morrisett dengan assembler yang dapat menjamin keamanan memori.

Logika Pengembaraan
sumber
0

Sedikit jawaban yang disederhanakan di sini, kenyataannya lebih rumit. Saya berharap perbedaan antara Assembler (A) dan Compiler (C) antara lain:

  1. Satu baris kode sumber berhubungan langsung dengan satu opcode CPU (A) atau tidak (C)
  2. Sangat tergantung pada CPU aktual (A) atau mesin independen (C)

Kita cenderung menyebut bahasa assembly "level rendah" dan bahasa sumber yang dipahami oleh kompiler "level tinggi" (ini adalah penyederhanaan, tapi tetap saja).

Dalam bahasa assembly Anda dapat melakukan operasi tambah dengan mengatakan:

  • tambahkan a, b (untuk satu CPU tertentu)
  • tambahkan R5, R6 (untuk CPU yang berbeda)
  • tambah (A5), D2 (untuk CPU berbeda)

Dalam bahasa tingkat tinggi Anda dapat menulis:

  • x = y + z;

Dan ini dapat menghasilkan satu instruksi atau ratusan instruksi tergantung pada sejumlah keadaan, salah satunya adalah apa yang CPU buat untuk kompiler.

Seperti yang Anda lihat, bahasa sumber assembly paling sering: (A) satu baris kode sumber memberikan satu baris opcode CPU dan sangat tergantung pada CPU yang Anda targetkan. Kompiler bahasa tingkat tinggi (C) menangani semua detail ini untuk Anda - satu baris kode sumber bisa menjadi nol, satu atau banyak opcode CPU dan kompiler menangani rincian apa yang dapat dilakukan CPU.

Kompiler saat ini sering terdiri dari beberapa tahapan yang berbeda. Mereka bisa dinamai frontend / backend atau beeing disebut hal-hal lain. Saya biasanya melihatnya sebagai empat tahap:

  1. Tahap pertama membaca kode sumber aktual dan membuat representasi internal. Tahap ini tahu bahasa sumber yang sebenarnya.
  2. Tahap kedua melihat representasi internal dan melakukan sejumlah optimasi. Saat ini, kompiler biasanya akan mencari untuk membuat program lebih cepat dan tidak peduli jika semakin besar. Optimalisasi dilakukan pada representasi internal. Menariknya, bagian-bagian ini bisa bersifat umum untuk beberapa bahasa yang berbeda.
  3. Tahap ketiga mengambil representasi internal dan membuat kode aktual untuk CPU yang dipilih. Mungkin ada beberapa versi berbeda dari tahap ini, yang menargetkan berbagai CPU. Akibatnya, Anda bisa menulis kode sumber sekali dan kemudian mengompilasinya untuk CPUS-s yang berbeda.
  4. Persiapan akhir untuk "mengemas" program (tahap ini bisa berupa tautan).

Menulis kompiler yang baik adalah profesi yang sangat terampil - membuat kompiler bahasa mainan dapat dilakukan pada sore hari oleh amatuer (atau well, sedikit lebih lama).

ghellquist
sumber