Baru-baru ini saya telah membaca beberapa arsip SO dan menemukan pernyataan yang menentang arsitektur x86.
Mengapa kita membutuhkan arsitektur CPU yang berbeda untuk server & mini / mainframe & mixed-core? mengatakan
" Arsitektur PC berantakan, setiap pengembang OS akan memberi tahu Anda hal itu. "Apakah mempelajari Bahasa Assembly sepadan dengan usahanya?( diarsipkan ) mengatakan
" Sadarilah bahwa arsitektur x86 paling buruk "Adakah cara mudah untuk mempelajari assembler x86? mengatakan
" Sebagian besar perguruan tinggi mengajarkan perakitan pada sesuatu seperti MIPS karena lebih mudah dipahami, perakitan x86 benar-benar jelek "
dan masih banyak lagi komentar suka
"Dibandingkan dengan kebanyakan arsitektur, X86 sangat payah."
" Sudah pasti kebijaksanaan konvensional bahwa X86 lebih rendah dari MIPS, SPARC, dan PowerPC "
Saya mencoba mencari tetapi tidak menemukan alasan apa pun. Saya tidak menemukan x86 buruk mungkin karena ini adalah satu-satunya arsitektur yang saya kenal.
Adakah yang bisa memberi saya alasan untuk mempertimbangkan x86 jelek / buruk / inferior dibandingkan dengan yang lain.
Jawaban:
Beberapa kemungkinan alasan untuk itu:
IN
danOUT
)kode assembly x86 rumit karena x86 adalah arsitektur yang rumit dengan banyak fitur. Daftar instruksi untuk mesin MIPS tipikal pas pada selembar kertas berukuran letter. Cantuman yang setara untuk x86 mengisi beberapa halaman, dan instruksinya melakukan lebih banyak, jadi Anda sering membutuhkan penjelasan yang lebih besar tentang apa yang mereka lakukan daripada yang dapat disediakan oleh daftar. Misalnya,
MOVSB
instruksi tersebut membutuhkan blok kode C yang relatif besar untuk menjelaskan fungsinya:Itu adalah instruksi tunggal yang melakukan pemuatan, penyimpanan, dan dua penambahan atau pengurangan (dikendalikan oleh input bendera), yang masing-masing akan menjadi instruksi terpisah pada mesin RISC.
Meskipun kesederhanaan MIPS (dan arsitektur serupa) tidak selalu membuatnya lebih unggul, untuk mengajarkan pengantar kelas assembler, masuk akal untuk memulai dengan ISA yang lebih sederhana . Beberapa kelas assembly mengajarkan subset x86 yang sangat disederhanakan yang disebut y86 , yang disederhanakan melampaui titik tidak berguna untuk penggunaan nyata (misalnya tidak ada instruksi shift), atau beberapa hanya mengajarkan instruksi dasar x86.
Pembaruan 2016: Anandtech telah memposting diskusi tentang ukuran opcode di bawah x64 dan AArch64 .
EDIT: Ini tidak seharusnya menjadi pesta x86! pesta. Saya tidak punya banyak pilihan selain melakukan sejumlah pukulan mengingat cara pertanyaan itu diucapkan. Tetapi dengan pengecualian (1), semua hal ini dilakukan untuk alasan yang baik (lihat komentar). Desainer Intel tidak bodoh - mereka ingin mencapai beberapa hal dengan arsitektur mereka, dan ini adalah beberapa pajak yang harus mereka bayarkan untuk mewujudkannya.
sumber
Ketukan utama terhadap x86 dalam pikiran saya adalah asal CISC - set instruksi berisi banyak interdependensi implisit. Saling ketergantungan ini mempersulit untuk melakukan hal-hal seperti penyusunan ulang instruksi pada chip, karena artefak dan semantik dari saling ketergantungan tersebut harus dipertahankan untuk setiap instruksi.
Sebagai contoh, sebagian besar instruksi penambahan & pengurangan bilangan bulat x86 memodifikasi register flag. Setelah melakukan penambahan atau pengurangan, operasi selanjutnya sering kali melihat register flag untuk memeriksa overflow, tanda bit, dll. Jika ada penambahan lain setelah itu, sangat sulit untuk mengetahui apakah aman untuk memulai eksekusi penambahan ke-2 sebelum hasil dari penambahan pertama diketahui.
Pada arsitektur RISC, instruksi add akan menentukan operan input dan register output, dan segala sesuatu tentang operasi akan berlangsung hanya dengan menggunakan register tersebut. Ini membuatnya lebih mudah untuk memisahkan operasi tambahan yang dekat satu sama lain karena tidak ada daftar bendera bloomin yang memaksa semuanya untuk berbaris dan mengeksekusi file tunggal.
Chip DEC Alpha AXP, desain RISC gaya MIPS, sangat sederhana dalam instruksi yang tersedia, tetapi set instruksi dirancang untuk menghindari ketergantungan register implisit antar-instruksi. Tidak ada daftar tumpukan yang ditentukan perangkat keras. Tidak ada register bendera yang ditentukan perangkat keras. Bahkan penunjuk instruksi adalah OS yang ditentukan - jika Anda ingin kembali ke pemanggil, Anda harus mengetahui bagaimana pemanggil akan memberi tahu Anda alamat mana yang harus dikembalikan. Ini biasanya ditentukan oleh konvensi pemanggilan OS. Pada x86, ini ditentukan oleh perangkat keras chip.
Bagaimanapun, lebih dari 3 atau 4 generasi desain chip Alpha AXP, perangkat keras berubah dari implementasi literal set instruksi sederhana dengan 32 register int dan 32 register float menjadi mesin eksekusi yang tidak sesuai pesanan dengan 80 register internal, penggantian nama register, penerusan hasil (di mana hasil dari instruksi sebelumnya diteruskan ke instruksi selanjutnya yang bergantung pada nilainya) dan semua jenis pemacu kinerja liar dan gila. Dan dengan semua lonceng dan peluit itu, die chip AXP masih jauh lebih kecil daripada die chip Pentium yang sebanding pada waktu itu, dan AXP jauh lebih cepat.
Anda tidak melihat lonjakan performa yang meningkatkan hal-hal dalam pohon keluarga x86 terutama karena kompleksitas set instruksi x86 membuat banyak jenis pengoptimalan eksekusi menjadi sangat mahal jika bukan tidak mungkin. Kejeniusan Intel adalah menyerah dalam mengimplementasikan set instruksi x86 dalam perangkat keras lagi - semua chip x86 modern sebenarnya adalah inti RISC yang pada tingkat tertentu menafsirkan instruksi x86, menerjemahkannya ke dalam kode mikro internal yang mempertahankan semua semantik dari x86 asli instruksi, tetapi memungkinkan untuk sedikit dari RISC yang rusak dan pengoptimalan lainnya melalui microcode.
Saya telah menulis banyak assembler x86 dan dapat sepenuhnya menghargai kenyamanan root CISC-nya. Tapi saya tidak sepenuhnya menghargai betapa rumitnya x86 sampai saya menghabiskan beberapa waktu menulis assembler Alpha AXP. Saya terkesima dengan kesederhanaan dan keseragaman AXP. Perbedaannya sangat besar dan dalam.
sumber
add
seterusnyaadd
. Aturannya jelas. Anda juga tidak perlu berurusan dengan penyusunan ulang instruksi. Sejak Pentium Pro di pertengahan 90-an, CPU melakukannya untuk Anda. Apa yang Anda sebutkan mungkin telah menjadi masalah 20 tahun yang lalu, tetapi saya tidak melihat alasan apa pun untuk menahannya terhadap arsitektur x86 saat ini.Arsitektur x86 berasal dari desain mikroprosesor 8008 dan kerabatnya. CPU ini dirancang pada saat memori lambat dan jika Anda bisa melakukannya dengan CPU mati, seringkali jauh lebih cepat. Namun, ruang mati CPU juga mahal. Dua alasan ini adalah mengapa hanya ada sedikit register yang cenderung memiliki tujuan khusus, dan set instruksi yang rumit dengan segala macam gotcha dan batasan.
Prosesor lain dari era yang sama (misalnya keluarga 6502) juga memiliki batasan dan kebiasaan serupa. Menariknya, baik seri 8008 dan seri 6502 dimaksudkan sebagai pengendali yang disematkan. Bahkan saat itu, pengontrol tertanam diharapkan untuk diprogram di assembler dan dalam banyak hal melayani programmer assembly daripada penulis kompiler. (Lihat chip VAX untuk apa yang terjadi ketika Anda melayani penulisan kompiler.) Para desainer tidak mengharapkan mereka menjadi platform komputasi tujuan umum; untuk itulah hal-hal seperti pendahulu dari arsitektur POWER. Revolusi Komputer Rumah mengubah itu, tentu saja.
sumber
Saya memiliki beberapa aspek tambahan di sini:
Pertimbangkan operasi "a = b / c" x86 akan mengimplementasikan ini sebagai
Sebagai bonus tambahan dari instruksi div, edx akan berisi sisanya.
Prosesor RISC akan membutuhkan pemuatan alamat b dan c terlebih dahulu, memuat b dan c dari memori ke register, melakukan pembagian dan memuat alamat a dan kemudian menyimpan hasilnya. Dst, sintaks src:
Di sini biasanya tidak akan ada sisa.
Jika ada variabel yang akan dimuat melalui pointer, kedua urutan dapat menjadi lebih panjang meskipun hal ini kecil kemungkinannya untuk RISC karena mungkin memiliki satu atau lebih pointer yang sudah dimuat di register lain. x86 memiliki register yang lebih sedikit sehingga kemungkinan pointer berada di salah satunya lebih kecil.
Pro dan kontra:
Instruksi RISC dapat dicampur dengan kode sekitarnya untuk meningkatkan penjadwalan instruksi, hal ini lebih kecil kemungkinannya dengan x86 yang sebaliknya melakukan pekerjaan ini (lebih atau kurang baik tergantung pada urutan) di dalam CPU itu sendiri. Urutan RISC di atas biasanya berukuran 28 byte (7 instruksi dengan lebar 32-bit / 4 byte masing-masing) pada arsitektur 32-bit. Ini akan menyebabkan memori off-chip bekerja lebih banyak saat mengambil instruksi (tujuh pengambilan). Urutan x86 yang lebih padat berisi lebih sedikit instruksi dan meskipun lebarnya bervariasi, Anda mungkin melihat rata-rata 4 byte / instruksi di sana juga. Bahkan jika Anda memiliki cache instruksi untuk mempercepat ini tujuh pengambilan berarti Anda akan memiliki defisit tiga di tempat lain untuk menebus dibandingkan dengan x86.
Arsitektur x86 dengan register yang lebih sedikit untuk disimpan / dipulihkan berarti ia mungkin akan melakukan thread switch dan menangani interupsi lebih cepat daripada RISC. Lebih banyak register untuk disimpan dan dipulihkan membutuhkan lebih banyak ruang tumpukan RAM sementara untuk melakukan interupsi dan lebih banyak ruang tumpukan permanen untuk menyimpan status utas. Aspek-aspek ini seharusnya membuat x86 menjadi kandidat yang lebih baik untuk menjalankan RTOS murni.
Pada catatan yang lebih pribadi, saya merasa lebih sulit untuk menulis rakitan RISC daripada x86. Saya menyelesaikan ini dengan menulis rutinitas RISC di C, menyusun dan memodifikasi kode yang dihasilkan. Ini lebih efisien dari sudut pandang produksi kode dan mungkin kurang efisien dari sudut pandang eksekusi. Semua 32 register itu untuk dilacak. Dengan x86, sebaliknya: 6-8 register dengan nama "asli" membuat masalah lebih mudah dikelola dan menambah keyakinan bahwa kode yang dihasilkan akan bekerja seperti yang diharapkan.
Jelek? Itu di mata yang melihatnya. Saya lebih suka "berbeda."
sumber
there typically won't be a reminder
tetapi wiki mengatakan bahwa mips memilikinya: en.wikipedia.org/wiki/MIPS_instruction_set#IntegerSaya pikir pertanyaan ini memiliki asumsi yang salah. Ini terutama hanya akademisi yang terobsesi dengan RISC yang menyebut x86 jelek. Pada kenyataannya, x86 ISA dapat dilakukan dalam operasi instruksi tunggal yang akan membutuhkan 5-6 instruksi pada ISA RISC. Penggemar RISC mungkin menentang bahwa x86 CPU modern memecah instruksi "kompleks" ini menjadi microops; namun:
mov %eax, 0x1c(%esp,%edi,4)
mode pengalamatan, dan ini tidak dipecah.x86 benar-benar menyerap semua aspek baik RISC sekitar 10-15 tahun yang lalu, dan kualitas RISC yang tersisa (sebenarnya yang menentukan - set instruksi minimal) berbahaya dan tidak diinginkan.
Selain dari biaya dan kompleksitas pembuatan CPU dan kebutuhan energinya, x86 adalah ISA terbaik . Siapa pun yang memberi tahu Anda sebaliknya, membiarkan ideologi atau agenda menghalangi penalaran mereka.
Di sisi lain, jika Anda menargetkan perangkat tersemat di mana biaya CPU diperhitungkan, atau perangkat tertanam / seluler di mana konsumsi energi menjadi perhatian utama, ARM atau MIPS mungkin lebih masuk akal. Perlu diingat meskipun Anda masih harus berurusan dengan ram ekstra dan ukuran biner yang diperlukan untuk menangani kode yang dengan mudah 3-4 kali lebih besar, dan Anda tidak akan bisa mendekati kinerjanya. Apakah ini penting tergantung banyak pada apa yang akan Anda jalankan di atasnya.
sumber
bahasa assembler x86 tidak terlalu buruk. Ketika Anda mendapatkan kode mesin yang mulai menjadi sangat jelek. Enkode instruksi, mode pengalamatan, dll jauh lebih rumit daripada yang ada pada kebanyakan CPU RISC. Dan ada kesenangan ekstra yang dibangun untuk tujuan kompatibilitas ke belakang - hal-hal yang hanya bekerja ketika prosesor dalam keadaan tertentu.
Dalam mode 16-bit, misalnya, pengalamatan bisa terlihat sangat aneh; ada mode pengalamatan untuk
[BX+SI]
, tetapi tidak untuk[AX+BX]
. Hal-hal seperti itu cenderung mempersulit penggunaan register, karena Anda perlu memastikan nilai Anda ada dalam register yang dapat Anda gunakan sesuai kebutuhan.(Untungnya, mode 32-bit jauh lebih waras (meskipun kadang-kadang masih agak aneh - segmentasi misalnya), dan kode x86 16-bit sebagian besar tidak relevan lagi di luar boot loader dan beberapa lingkungan yang disematkan.)
Ada juga sisa-sisa dari masa lalu, ketika Intel mencoba menjadikan x86 sebagai prosesor terbaik. Instruksi beberapa byte panjang yang melakukan tugas yang sebenarnya tidak dilakukan siapa pun lagi, karena terus terang terlalu lambat atau rumit. Instruksi ENTER dan LOOP , untuk dua contoh - perhatikan kode C stack frame seperti "push ebp; mov ebp, esp" dan bukan "enter" untuk kebanyakan kompiler.
sumber
Saya bukan ahli, tetapi tampaknya banyak fitur yang tidak disukai orang bisa menjadi alasan mengapa fitur ini berfungsi dengan baik. Beberapa tahun yang lalu, memiliki register (bukan tumpukan), register frame, dll. Dipandang sebagai solusi yang bagus untuk membuat arsitektur tampak lebih sederhana bagi manusia. Namun, saat ini, yang penting adalah kinerja cache, dan kata-kata dengan panjang variabel x86 memungkinkannya untuk menyimpan lebih banyak instruksi dalam cache. The "instruksi decode", yang saya percaya lawan menunjukkan sekali mengambil setengah chip, hampir tidak seperti itu lagi.
Menurut saya paralelisme adalah salah satu faktor terpenting saat ini - setidaknya untuk algoritme yang sudah berjalan cukup cepat agar dapat digunakan. Mengekspresikan paralelisme tinggi dalam perangkat lunak memungkinkan perangkat keras untuk mengamortisasi (atau sering kali menyembunyikan sepenuhnya) latensi memori. Tentu saja, masa depan arsitektur yang lebih jauh mungkin dalam sesuatu seperti komputasi kuantum.
Saya telah mendengar dari nVidia bahwa salah satu kesalahan Intel adalah mereka menyimpan format biner dekat dengan perangkat keras. PTX CUDA melakukan beberapa kalkulasi penggunaan register cepat (pewarnaan grafik), jadi nVidia dapat menggunakan mesin register daripada mesin stack, tetapi masih memiliki jalur peningkatan yang tidak merusak semua perangkat lunak lama.
sumber
Selain alasan orang telah menyebutkan:
__cdecl
,__stdcall
,__fastcall
, dllsumber
Saya rasa Anda akan mendapatkan sebagian dari jawabannya jika Anda pernah mencoba menulis kompiler yang menargetkan x86, atau jika Anda menulis emulator mesin x86, atau bahkan jika Anda mencoba menerapkan ISA dalam desain perangkat keras.
Meskipun saya mengerti bahwa "x86 jelek!" argumen, saya masih berpikir itu lebih menyenangkan menulis perakitan x86 daripada MIPS (misalnya) - yang terakhir hanya membosankan. Itu selalu dimaksudkan untuk menjadi baik bagi penyusun daripada untuk manusia. Saya tidak yakin sebuah chip bisa lebih memusuhi penulis kompiler jika dicoba ...
Bagian paling jelek bagi saya adalah cara kerja segmentasi (mode-nyata) - bahwa setiap alamat fisik memiliki 4096 segmen: alias offset. Kapan terakhir kali Anda membutuhkannya ? Segalanya akan jauh lebih sederhana jika bagian segmen benar-benar bit orde tinggi dari alamat 32-bit.
sumber
x86 memiliki register tujuan umum yang sangat, sangat terbatas
itu mempromosikan gaya pengembangan yang sangat tidak efisien pada tingkat terendah (neraka CISC) daripada metodologi muat / penyimpanan yang efisien
Intel membuat keputusan mengerikan untuk memperkenalkan segmen / offset - model alamat memori yang jelas-jelas bodoh agar tetap kompatibel dengan (saat ini sudah!) Teknologi usang
Pada saat semua orang menggunakan 32 bit, x86 menahan dunia PC arus utama dengan menjadi 16 bit yang sedikit (kebanyakan - 8088 - bahkan hanya dengan jalur data eksternal 8 bit, yang bahkan lebih menakutkan!) CPU
Bagi saya (dan saya adalah veteran DOS yang telah melihat setiap generasi PC dari perspektif pengembang!) Poin 3. adalah yang terburuk.
Bayangkan situasi berikut yang kami alami di awal 90-an (arus utama!):
a) Sistem operasi yang memiliki batasan tidak wajar karena alasan lama (640kB RAM yang mudah diakses) - DOS
b) Ekstensi sistem operasi (Windows) yang dapat melakukan lebih banyak hal dalam hal RAM, tetapi terbatas pada hal-hal seperti game, dll ... dan bukan hal yang paling stabil di Bumi (untungnya ini berubah nanti, tetapi saya Saya berbicara tentang awal 90-an di sini)
c) Sebagian besar perangkat lunak masih DOS dan kami harus sering membuat boot disk untuk perangkat lunak khusus, karena ada EMM386.exe ini yang disukai beberapa program, yang lain dibenci (terutama gamer - dan saya adalah gamer AVID saat ini - tahu apa yang saya sedang berbicara tentang di sini)
d) Kami terbatas pada MCGA 320x200x8 bits (ok, ada sedikit lagi dengan trik khusus, 360x480x8 dimungkinkan, tetapi hanya tanpa dukungan runtime library), yang lainnya berantakan dan mengerikan ("VESA" - lol)
e) Namun dalam hal perangkat keras, kami memiliki mesin 32 bit dengan RAM dan kartu VGA yang cukup banyak dengan dukungan hingga 1024x768
Alasan situasi buruk ini?
Keputusan desain sederhana dari Intel. Kompatibilitas level instruksi mesin (BUKAN level biner!) Dengan sesuatu yang sudah sekarat, saya pikir itu adalah 8085. Masalah lain yang tampaknya tidak terkait (mode grafis, dll ...) terkait karena alasan teknis dan karena sangat sempit arsitektur minded yang dibawa oleh platform x86 dengan sendirinya.
Saat ini, situasinya berbeda, tetapi tanyakan pada pengembang assembler atau orang yang membuat backend compiler untuk x86. Jumlah register tujuan umum yang sangat rendah tidak lain adalah pembunuh kinerja yang mengerikan.
sumber