Mengapa x86 jelek? Mengapa dianggap inferior jika dibandingkan dengan yang lain? [Tutup]

105

Baru-baru ini saya telah membaca beberapa arsip SO dan menemukan pernyataan yang menentang arsitektur x86.

dan masih banyak lagi komentar suka

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.

cakar
sumber
1
Saya akan menggunakan S&A berdasarkan jawaban sejauh ini, tetapi saya akan mencatat secara sepintas bahwa CISC bukan masalah untuk set instruksi m68k. x86 adalah apa adanya, dan Anda dapat menyimpannya.
dmckee --- mantan moderator anak kucing
apa itu "S&A"? "CISC bukan masalah untuk set instruksi m68k." -- Kenapa tidak?
cakar
5
Chip motorala 68000 series memiliki arsitektur yang sangat CISC, tetapi memiliki set instruksi yang seragam, cukup ortogonal, dan sangat mudah. Mengapa perbedaan dari x86? Saya tidak tahu. Tetapi perhatikan bahwa ada perbedaan besar antara kompleksitas dalam chip dan kompleksitas dalam set instruksi (yaitu dalam antarmuka yang dilihat oleh programmer perakitan).
dmckee --- kucing mantan moderator
4
1 untuk pertanyaan yang sangat menarik.
Turing Selesai
1
Studi terbaru tentang efisiensi energi dari berbagai prosesor ditemukan di sini, dengan diskusi yang baik tentang apa yang mendorong desain CISC & RISC. extremetech.com/extreme/…

Jawaban:

93

Beberapa kemungkinan alasan untuk itu:

  1. x86 adalah ISA yang relatif lama (bagaimanapun, leluhurnya adalah 8086)
  2. x86 telah berkembang secara signifikan beberapa kali, tetapi perangkat keras diperlukan untuk menjaga kompatibilitas mundur dengan binari lama. Misalnya, perangkat keras x86 modern masih berisi dukungan untuk menjalankan kode 16 bit secara native. Selain itu, beberapa model pengalamatan memori tersedia untuk memungkinkan kode yang lebih lama beroperasi secara bergantian pada prosesor yang sama, seperti mode nyata, mode terlindungi, mode virtual 8086, dan mode panjang (amd64). Ini bisa membingungkan beberapa orang.
  3. x86 adalah mesin CISC. Untuk waktu yang lama, hal ini berarti lebih lambat daripada mesin RISC seperti MIPS atau ARM, karena instruksi memiliki interdependensi data dan tanda yang membuat sebagian besar bentuk paralelisme tingkat instruksi sulit untuk diterapkan. Implementasi modern menerjemahkan instruksi x86 ke dalam instruksi mirip RISC yang disebut " operasi mikro " di bawah sampul untuk membuat jenis pengoptimalan ini praktis untuk diterapkan di perangkat keras.
  4. Dalam beberapa hal, x86 tidak kalah, hanya berbeda. Misalnya, input / output ditangani sebagai pemetaan memori pada sebagian besar arsitektur, tetapi tidak pada x86. (NB: Mesin x86 modern biasanya memiliki beberapa bentuk dukungan DMA , dan berkomunikasi dengan perangkat keras lain melalui pemetaan memori; tetapi ISA masih memiliki instruksi I / O seperti INdan OUT)
  5. ISA x86 memiliki register arsitektur yang sangat sedikit, yang dapat memaksa program untuk melakukan perjalanan bolak-balik melalui memori lebih sering daripada yang diperlukan. Instruksi tambahan yang diperlukan untuk melakukan ini membutuhkan sumber daya eksekusi yang dapat digunakan untuk pekerjaan yang berguna, meskipun penerusan penyimpanan efisienmenjaga latensi tetap rendah. Implementasi modern dengan penggantian nama register menjadi file register fisik yang besar dapat menyimpan banyak instruksi dalam penerbangan, tetapi kurangnya register arsitektural masih merupakan kelemahan yang signifikan untuk 32-bit x86. Peningkatan x86-64 dari 8 menjadi 16 register integer dan vektor adalah salah satu faktor terbesar dalam kode 64bit yang lebih cepat dari 32-bit (bersama dengan register-call ABI yang lebih efisien), bukan peningkatan lebar setiap register. Peningkatan lebih lanjut dari 16 menjadi 32 register integer akan membantu beberapa, tapi tidak sebanyak itu. (AVX512 memang meningkat menjadi 32 register vektor, karena kode floating-point memiliki latensi lebih tinggi dan seringkali membutuhkan lebih banyak konstanta.) ( Lihat komentar )
  6. 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, MOVSBinstruksi tersebut membutuhkan blok kode C yang relatif besar untuk menjelaskan fungsinya:

    if (DF==0) 
      *(byte*)DI++ = *(byte*)SI++; 
    else 
      *(byte*)DI-- = *(byte*)SI--;
    

    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.

  7. X86 menggunakan opcode dengan panjang variabel, yang menambahkan kompleksitas perangkat keras sehubungan dengan penguraian instruksi. Di era modern biaya ini menjadi semakin kecil karena CPU menjadi semakin dibatasi oleh bandwidth memori daripada oleh komputasi mentah, tetapi banyak artikel dan sikap "bashing x86" datang dari era ketika biaya ini secara komparatif jauh lebih besar.
    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.

Billy ONeal
sumber
17
Ini pengorbanan. Ini adalah kekuatan karena ukuran biner mungkin lebih kecil, tetapi kelemahannya adalah Anda harus memiliki perangkat keras yang sangat rumit untuk mengimplementasikan parser untuk instruksi ini. Sebagian besar instruksi memiliki ukuran yang sama - sebagian besar alasan opcode panjang variabel pada x86 adalah ketika mereka memutuskan untuk menambahkan fitur dan ternyata mereka tidak dapat mewakili apa yang mereka inginkan dalam jumlah bit yang harus mereka kerjakan . Sebagian besar orang tidak terlalu mementingkan ukuran biner sebanyak kerumitan perangkat keras atau konsumsi daya.
Billy ONeal
8
@Joey Adams: Bandingkan instruksi panjang variabel x86 dengan Mode Thumb ARM ( en.wikipedia.org/wiki/ARM_architecture#Thumb ). Mode Thumb menghasilkan kode objek yang jauh lebih kecil untuk ARM karena instruksi yang lebih pendek langsung dipetakan ke instruksi normal. Tapi karena ada pemetaan 1: 1 antara instruksi yang lebih besar dan yang lebih kecil, perangkat keras parsing mudah diimplementasikan. Instruksi panjang variabel x86 tidak memiliki manfaat ini karena mereka tidak dirancang seperti itu sejak awal.
Billy ONeal
7
(6) Tidak setiap op-code perlu digunakan oleh setiap program, tapi sial, ketika saya membutuhkan SSE3, saya senang saya memilikinya.
Chris K
4
@ Chris Kaminski: Bagaimana hal itu tidak mempengaruhi perangkat keras? Tentu, pada komputer modern berukuran penuh tidak ada yang akan peduli, tetapi jika saya membuat sesuatu seperti ponsel, saya lebih peduli tentang konsumsi daya daripada hampir semua hal lainnya. Opcode panjang variabel tidak meningkatkan waktu eksekusi tetapi perangkat keras decode masih membutuhkan daya untuk beroperasi.
Billy ONeal
5
Yang merupakan salah satu hal yang membuat set instruksi x86 sangat jelek, karena ia tidak dapat memutuskan apakah itu akumulator atau arsitektur berbasis file register (meskipun ini sebagian besar telah diperbaiki dengan 386, yang membuat set instruksi jauh lebih ortogonal , terlepas dari apa pun yang dikatakan penggemar 68k kepada Anda).
ninjalj
25

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.

dthorpe.dll
sumber
6
Saya akan mendengarkan tidak ada bashing dari CISC sendiri kecuali dan sampai Anda dapat menjelaskan m68k.
dmckee --- mantan moderator anak kucing
2
Saya tidak terbiasa dengan m68k, jadi saya tidak bisa mengkritiknya.
dthorpe
4
Saya rasa jawaban ini tidak cukup buruk untuk di-downvote, tetapi menurut saya keseluruhan argumen "RISC lebih kecil dan lebih cepat daripada CISC" tidak terlalu relevan di era modern. Tentu, AXP mungkin jauh lebih cepat untuk saat ini, tetapi faktanya adalah bahwa RISC modern dan CISC modern hampir sama dalam hal kinerja. Seperti yang saya katakan dalam jawaban saya, sedikit penalti daya untuk dekode x86 adalah alasan untuk tidak menggunakan x86 untuk sesuatu seperti ponsel, tapi itu argumen kecil untuk desktop atau notebook berukuran penuh.
Billy ONeal
4
@ Billy: size lebih dari sekedar ukuran kode atau ukuran instruksi. Intel membayar cukup banyak penalti di area permukaan chip untuk menerapkan logika perangkat keras untuk semua instruksi khusus tersebut, inti microcode RISC di bawah tenda atau tidak. Ukuran cetakan berdampak langsung pada biaya pembuatan, jadi ini masih menjadi perhatian yang valid dengan desain sistem modern.
dthorpe
1
@dthorpe: Saya tidak setuju dengan sebagian besar, jika tidak semua, yang Anda tulis. Sejak 8086, Anda tidak perlu khawatir apakah aman untuk dieksekusi dan addseterusnya add. 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.
Nathan Fellman
21

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.

statika
sumber
4
+1 untuk satu-satunya jawaban di sini dari seseorang yang sebenarnya tampaknya memiliki latar belakang sejarah tentang masalah tersebut.
Billy ONeal
3
Memori selalu lambat. Mungkin (secara relatif) lebih lambat hari ini daripada ketika saya mulai dengan Z80s dan CP / M pada tahun 1982. Kepunahan bukanlah satu-satunya jalur evolusi karena dengan kepunahan arah evolusi tertentu berhenti. Saya akan mengatakan x86 telah beradaptasi dengan baik dalam 28 tahun (sejauh ini keberadaannya).
Olof Forshell
4
Kecepatan memori sempat mendekati paritas dengan CPU sekitar waktu 8086. 9900 dari Texas Instruments memiliki desain yang hanya berfungsi karena ini terjadi. Tapi kemudian CPU berpacu ke depan lagi dan tetap di sana. Hanya sekarang, ada cache untuk membantu mengelola ini.
staticsan
3
@Olof Forshell: Ini adalah assembler yang kompatibel dalam kode perakitan 8080 yang dapat diterjemahkan menjadi kode 8086. Dari sudut pandang itu, itu adalah 8.080 plus ekstensi, seperti Anda dapat melihat 8.080 sebagai 8008 plus ekstensi.
David Thornley
3
@Olof Forshell: Kecuali bahwa 8086 telah dirancang untuk mewujudkannya. Itu merupakan perpanjangan dari 8080, dan sebagian besar (mungkin semua) instruksi 8080 dipetakan satu-ke-satu, dengan semantik yang jelas serupa. Itu tidak berlaku untuk arsitektur IBM 360, tidak peduli ke mana Anda ingin mendorongnya.
David Thornley
13

Saya memiliki beberapa aspek tambahan di sini:

Pertimbangkan operasi "a = b / c" x86 akan mengimplementasikan ini sebagai

  mov eax,b
  xor edx,edx
  div dword ptr c
  mov a,eax

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:

  mov r5,addr b
  mov r5,[r5]
  mov r6,addr c
  mov r6,[r6]
  div r7,r5,r6
  mov r5,addr a
  mov [r5],r7

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."

Olof Forshell
sumber
a, b dan c dalam contoh saya harus dipandang sebagai variabel berbasis memori dan bukan nilai langsung.
Olof Forshell
... "dword ptr" digunakan untuk menentukan ukuran variabel yang ukurannya tidak diketahui jika, misalnya, hanya dideklarasikan sebagai eksternal atau jika Anda malas.
Olof Forshell
2
Itu bukan pertama kalinya saya mendengar saran untuk menulisnya dalam C terlebih dahulu, lalu menyaringnya menjadi assembler. Itu pasti membantu
Joe Plante
Pada masa-masa awal semua prosesor adalah RISC. CISC muncul sebagai strategi mitigasi untuk sistem memori inti besi yang SANGAT lambat, sehingga CISC, dengan instruksi yang lebih sedikit dan lebih kuat, mengurangi tekanan pada subsistem memori, dan memanfaatkan bandwidth dengan lebih baik. Demikian pula, register pada awalnya dianggap sebagai lokasi memori di dalam chip di dalam CPU untuk melakukan akumulasi. Terakhir kali saya secara serius melakukan benchmark terhadap mesin RISC adalah 1993 - SPARC dan HP Prisim. SPARC sangat buruk di seluruh papan. Prisim naik hingga 20x secepat 486 pada add / sub / mul tetapi tersedot pada transendental. CISC lebih baik.
@OlofForshell Anda mengatakan there typically won't be a remindertetapi wiki mengatakan bahwa mips memilikinya: en.wikipedia.org/wiki/MIPS_instruction_set#Integer
Alex Zhukovskiy
10

Saya 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:

  1. Dalam banyak kasus, itu hanya sebagian benar atau tidak benar sama sekali. Instruksi "kompleks" yang paling berguna di x86 adalah hal-hal seperti mov %eax, 0x1c(%esp,%edi,4)mode pengalamatan, dan ini tidak dipecah.
  2. Apa yang seringkali lebih penting pada mesin modern bukanlah jumlah siklus yang dihabiskan (karena sebagian besar tugas tidak terikat cpu) tetapi dampak cache instruksi dari kode. 5-6 instruksi ukuran tetap (biasanya 32bit) akan mempengaruhi cache lebih dari satu instruksi kompleks yang jarang lebih dari 5 byte.

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.

R .. GitHub BERHENTI ICE BANTUAN
sumber
3
di mana konsumsi energi menjadi perhatian utama, ARM atau MIPS mungkin lebih masuk akal ... jadi, jika ada setidaknya satu aspek di mana ARM atau MIPS lebih masuk akal, bukankah itu membuat x86 belum tentu merupakan ISA terbaik?
Shahbaz
Itu sebabnya saya memenuhi syarat "yang terbaik" dengan "selain dari biaya ... dan kebutuhan energi mereka".
R .. GitHub STOP HELPING ICE
1
Saya pikir Intel memperlambat kecepatan CPU, dan ukuran die yang lebih kecil telah menghilangkan sebagian besar perbedaan daya. CPU 64-bit ganda Celeron baru dengan 64k L1 dan 1MB L2 cache adalah chip 7,5 watt. Ini mesin tempat nongkrong "Starbucks" saya, dan masa pakai baterainya sangat panjang dan akan berputar di sekitar mesin P6. Sebagai seorang pria yang melakukan sebagian besar perhitungan floating point, saya menyerah pada RISC sejak lama. Itu hanya merangkak. SPARC khususnya sangat glasial. Contoh sempurna mengapa RISC menyebalkan adalah CPU Intel i860. Intel tidak pernah pergi KE SANA lagi.
@RocketRoy: 7,5 watt tidak benar-benar dapat diterima untuk perangkat yang bertenaga 24/7 (dan tidak melakukan perhitungan yang berguna sepanjang waktu) atau menggunakan baterai 3,7v / 2000mAh.
R .. GitHub STOP HELPING ICE
2
@RocketRoy "Intel i860 CPU. Intel tidak pernah pergi KE SANA lagi." Setelah sedikit riset, i860 terdengar sangat mirip dengan Itanium: VLIW, paralelisme instruksi yang dipesan kompiler ....
Jonathon Reinhart
9

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.

cHao
sumber
2
Saya yakin masalah "enter" versus "push / mov" muncul karena pada beberapa prosesor, "push / mov" lebih cepat. Pada beberapa prosesor, "masuk" lebih cepat. C'est la vie.
Dietrich Epp
4
Ketika saya dipaksa untuk menggunakan mesin berbasis x86 dan mulai melihatnya (memiliki latar belakang m68k), saya mulai merasa pemrograman asm membuat frustrasi, ... seperti jika saya telah belajar pemrograman dengan bahasa seperti C, dan kemudian menjadi dipaksa untuk berhubungan dengan asm ... Anda "merasa" Anda kehilangan kekuatan ekspresi, kemudahan, kejelasan, "koherensi", "intuisi". Saya yakin bahwa jika saya akan memulai pemrograman asm dengan x86, saya akan berpikir tidak terlalu buruk ... mungkin ... Saya juga melakukan MMIX dan MIPS, dan "asm lang" mereka jauh lebih baik daripada x86 (jika ini adalah PoV yang tepat untuk Q, tapi mungkin juga tidak)
ShinTakezou
Masalah mode pengalamatan telah diperbaiki di 80386. Hanya kode 16 bit yang memiliki mode pengalamatan terbatas, kode 32 bit jauh lebih baik. Anda bisa mendapatkan mode pengalamatan 32 bit dalam kode 16 bit menggunakan awalan khusus dan sebaliknya.
fuz
@FUZxxl: Ya ... saya mungkin seharusnya menyebutkan bahwa keburukan sebagian besar terbatas pada kode 16-bit. Tetap (menurut saya). :)
cHao
Inelegance yang dirasakan sebagian besar berasal dari kesalahpahaman bahwa register dari 8086 adalah register bertujuan umum; itu tidak benar. Masing-masing memiliki tujuan khusus dan jika Anda tidak berpegang pada tujuan mereka, Anda akan mengalami saat yang buruk.
fuz
3

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.

gatoatigrado.dll
sumber
9
RISC tidak dirancang dengan mempertimbangkan pengembang manusia. Salah satu ide di balik RISC adalah untuk memindahkan beberapa kompleksitas chip ke siapa pun yang menulis rakitan, idealnya kompiler. Lebih banyak register berarti lebih sedikit penggunaan memori dan lebih sedikit ketergantungan antar instruksi, memungkinkan pipeline yang lebih dalam dan kinerja yang lebih tinggi. Perhatikan bahwa x86-64 memiliki register umum dua kali lebih banyak daripada x86, dan ini saja yang bertanggung jawab atas peningkatan kinerja yang signifikan. Dan instruksi pada sebagian besar chip x86 didekode sebelum di-cache, bukan setelahnya (jadi ukuran tidak menjadi masalah di sini).
Dietrich Epp
3
@Dietrich Epp: Itu tidak sepenuhnya benar. X86-64 memang memiliki lebih banyak register yang terlihat di ISA, tetapi implementasi x86 modern biasanya memiliki file register gaya RISC yang dipetakan ke register ISA sesuai permintaan untuk mempercepat eksekusi.
Billy ONeal
"Saya telah mendengar dari nVidia bahwa salah satu kesalahan Intel adalah mereka menyimpan format biner dekat dengan perangkat keras." - Saya tidak mendapatkan ini dan bagian PTX CUDA.
cakar
1
@Dietrech Epp: "Dan instruksi pada kebanyakan chip x86 didekodekan sebelum mereka di-cache, bukan setelah" Itu tidak benar. Mereka di-cache sebelum diterjemahkan. Saya yakin Pentium 4 memiliki cache jejak tambahan yang di-cache setelah decode, tetapi itu telah dihentikan.
Nathan Fellman
Itu tidak benar, prosesor "jembatan berpasir" terbaru menggunakan semacam cache jejak (seperti itu untuk pentium 4, oh bocah tua itu: D), jadi teknologi pergi dan kembali ...
Quonux
3

Selain alasan orang telah menyebutkan:

  • x86-16 memiliki skema pengalamatan memori yang agak aneh yang memungkinkan satu lokasi memori untuk ditangani hingga 4096 cara berbeda, RAM terbatas hingga 1 MB, dan memaksa pemrogram untuk menangani dua ukuran pointer yang berbeda. Untungnya, perpindahan ke 32-bit membuat fitur ini tidak diperlukan, tetapi chip x86 masih membawa inti register segmen.
  • Meskipun bukan kesalahan dari x86 per se , x86 memanggil konvensi yang tidak standar seperti MIPS adalah (terutama karena MS-DOS tidak datang dengan kompiler), meninggalkan kami dengan kekacauan __cdecl, __stdcall, __fastcall, dll
dan04
sumber
Hmm .. ketika saya memikirkan pesaing x86, saya tidak memikirkan MIPS. ARM atau PowerPC mungkin ....
Billy ONeal
@ Billy: x86 telah ada di dekat selamanya. MIPS pernah menjadi pesaing x86. Seperti yang saya ingat, x86 telah melakukan tugasnya untuk mencapai tingkat di mana ia dapat bersaing dengan MIPS. (Dulu ketika MIPS dan SPARC bertarung di arena workstation.)
Shannon Severance
@ Shannon Severance: Hanya karena sesuatu yang dulu tidak berarti sesuatu yang demikian.
Billy ONeal
2
@supercat: apa yang orang-orang di era model memori datar x86-32 cenderung lupa adalah bahwa 16 bit berarti 64k memori (siapa pun yang mengganggu matematika akan mengerti bahwa sihir tidak mungkin, bahwa 8086 bukanlah hukuman kejam bagi programmer yang tidak menaruh curiga). Ada beberapa cara untuk mengatasi 64k tetapi solusi 8086 adalah kompromi yang baik.
Olof Forshell
2
@OlofForshell: Saya pikir banyak orang mengeluhkan fakta bahwa 8086 tidak sebaik 68000 (yang memiliki ruang pengalamatan linier 16MB dan jalur yang jelas ke 4 pertunjukan). Tentu saja menggunakan prosesor 32-bit akan mempermudah akses lebih dari 64K, tetapi 8086 adalah arsitektur 16-bit yang dirancang sebagai langkah maju dari 8-bit 8080. Saya tidak melihat alasan Intel harus melompat langsung dari 8-bit ke 32-bit.
supercat
3

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.

Bernd Jendrissek
sumber
m68k jauh lebih lucu, dan lebih baik bagi manusia daripada x86 (yang tidak tampak begitu "manusiawi" bagi banyak pemrogram m68k), jika PoV yang tepat adalah cara manusia dapat menulis kode di rakitan tersebut.
ShinTakezou
Segmen: pengalamatan offset merupakan upaya untuk tetap kompatibel sampai batas tertentu dengan CP / M-world. Salah satu keputusan terburuk yang pernah ada.
Turing Selesai
@ Tur Selesai: segmen: offset pada dasarnya BUKAN merupakan upaya untuk tetap kompatibel dengan dunia CP / M. Apa itu adalah upaya yang sangat sukses untuk memungkinkan prosesor 16 bit menangani lebih dari 64 KByte dengan menempatkan kode, data, tumpukan, dan area memori lainnya di segmen yang berbeda.
Olof Forshell
1
Pada kenyataannya, menempatkan data dan tumpukan di segmen yang berbeda sama sekali tidak berguna untuk C; itu hanya dapat digunakan untuk asm. Di C, penunjuk dapat menunjuk ke data dengan durasi penyimpanan yang dialokasikan secara statis, otomatis, atau dinamis, jadi tidak ada cara untuk menghilangkan segmen tersebut. Mungkin berguna untuk Pascal atau Fortran atau semacamnya, tapi tidak untuk C, yang sudah menjadi bahasa dominan saat itu ...
R .. GitHub STOP HELPING ICE
2
@Bernd: Alasan fs / gs dipilih untuk penyimpanan lokal thread bukanlah karena register segmen cocok untuk ini. Hanya saja x86 sangat kekurangan register, dan register segmen tidak digunakan. Register serba guna yang menunjuk ke struktur utas akan bekerja dengan baik, dan pada kenyataannya banyak sistem RISC dengan lebih banyak register menggunakan satu sebagai penunjuk utas.
R .. GitHub STOP HELPING ICE
1
  1. x86 memiliki register tujuan umum yang sangat, sangat terbatas

  2. itu mempromosikan gaya pengembangan yang sangat tidak efisien pada tingkat terendah (neraka CISC) daripada metodologi muat / penyimpanan yang efisien

  3. Intel membuat keputusan mengerikan untuk memperkenalkan segmen / offset - model alamat memori yang jelas-jelas bodoh agar tetap kompatibel dengan (saat ini sudah!) Teknologi usang

  4. 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.

Turing Lengkap
sumber
Satu-satunya masalah utama dengan arsitektur tersegmentasi 8086 adalah bahwa hanya ada satu register segmen (ES) non-dedicated, dan bahasa pemrograman tidak dirancang untuk bekerja dengannya secara efektif. Gaya pengalamatan berskala yang digunakannya akan bekerja dengan sangat baik dalam bahasa berorientasi objek yang tidak mengharapkan objek dapat dimulai dari alamat sewenang-wenang (jika seseorang menyelaraskan objek pada batas paragraf, referensi objek hanya perlu dua byte daripada empat). Jika seseorang membandingkan kode Macintosh awal dengan kode PC, 8086 sebenarnya terlihat cukup bagus dibandingkan dengan 68000.
supercat
@supercat: sebenarnya, register es itu didedikasikan untuk sesuatu, yaitu untuk instruksi string yang memerlukan penyimpanan (movs, stos) atau pemindaian (cmps dan scas). Mengingat pengalamatan 64KiB dari setiap register segmen, es juga menyediakan "tautan yang hilang" ke memori selain kode, data, dan memori tumpukan (cs, ds, ss). Register segmen menyediakan semacam skema proteksi memori yang tidak dapat Anda atasi di luar blok memori 64Kib register. Solusi apa yang lebih baik yang Anda usulkan karena x86 merupakan arsitektur 16-bit dan batasan litografi saat itu?
Olof Forshell
@OlofForshell: ES digunakan untuk instruksi string, tetapi dapat digunakan sebagai register tanpa ikatan untuk kode yang tidak menggunakannya. Cara untuk meredakan hambatan seg-reg tanpa memerlukan terlalu banyak ruang opcode adalah dengan memiliki awalan "rseg" yang akan menentukan bahwa untuk instruksi format r / m berikut, bidang "r" akan memilih dari CS / SS / DS / ES / FS / GS / ?? / ?? alih-alih AX / BX / CX / DX / SI / DI / SP / BP, dan memiliki awalan untuk FS / GS dan instruksi untuk LFS dan LGS (seperti LDS dan LES). Saya tidak tahu bagaimana mikro-arsitektur untuk 8086 ditata, tapi menurut saya hal seperti itu bisa berhasil.
supercat
@supercat: seperti yang saya tulis, "register es juga menyediakan link yang hilang ke memori selain ..." Fs dan gs tidak tiba sampai 386 seingat saya.
Olof Forshell
1
@OlofForshell: Mereka tidak melakukannya, yang membuat arsitektur 80286 bahkan lebih buruk daripada arsitektur 8086 dalam banyak hal. Maksud saya adalah bahwa menambahkan beberapa register segmen lagi (atau bahkan satu, dalam hal ini) akan membuat arsitektur 8086 jauh lebih berguna, dan set instruksi bisa lebih bersih dan lebih berguna jika register segmen dapat diakses seperti yang lain.
supercat