Apa kelebihan format endian kecil?


140

Prosesor Intel (dan mungkin beberapa yang lain) menggunakan format endian kecil untuk penyimpanan.

Saya selalu bertanya-tanya mengapa seseorang ingin menyimpan byte dalam urutan terbalik. Apakah format ini memiliki kelebihan dibandingkan format big endian?


1
6502 adalah prosesor pipelined awal (pertama?). Sepertinya saya ingat beberapa klaim tentang hal itu sebagai little-endian untuk beberapa masalah yang berhubungan dengan kinerja karena pipa - tapi saya tidak tahu sekarang apa masalah itu. Ada saran?
Steve314

1
@ Steve314: Jawaban saya menjelaskan bagaimana sedikit endian membantu kinerja dalam pipelined CPU: programmers.stackexchange.com/q/95854/27874
Martin Vilcans

3
Little-endian, big-endian - Anda harus memilih satu atau yang lain. Seperti mengemudi di sisi kiri atau kanan jalan.

3
Saya menyarankan Anda untuk menulis beberapa kode dalam ASM, lebih disukai untuk arsitektur "old-school" seperti 6502 atau Z80. Anda akan segera melihat mengapa ini menggunakan endian kecil. Arsitektur yang menggunakan big endian memiliki karakteristik tertentu pada set instruksi mereka yang menjadikan format itu lebih disukai. Itu bukan keputusan yang sewenang-wenang untuk dibuat!
Stefan Paul Noack

2
Setiap sistem byte-order memiliki kelebihannya. Mesin Little-endian membiarkan Anda membaca byte terendah terlebih dahulu, tanpa membaca yang lain. Anda dapat memeriksa apakah suatu angka ganjil atau genap (bit terakhir adalah 0) dengan sangat mudah, yang keren jika Anda menyukai hal semacam itu. Sistem big-endian menyimpan data dalam memori dengan cara yang sama seperti yang kita pikirkan tentang data (kiri-ke-kanan), yang membuat proses debug tingkat rendah lebih mudah.
Koray Tugay

Jawaban:


198

Ada beberapa argumen baik, tetapi satu titik adalah bahwa dalam sistem little-endian, alamat nilai yang diberikan dalam memori, diambil sebagai lebar 32, 16, atau 8 bit, adalah sama.

Dengan kata lain, jika Anda memiliki dalam memori nilai dua byte:

0x00f0   16
0x00f1    0

menganggap '16' sebagai nilai 16-bit (c 'singkat' pada sebagian besar sistem 32-bit) atau sebagai nilai 8-bit (umumnya c 'char') hanya mengubah instruksi pengambilan yang Anda gunakan - bukan alamat yang Anda ambil dari.

Pada sistem big-endian, dengan yang diuraikan sebagai:

0x00f0    0
0x00f1   16

Anda perlu menambah pointer dan kemudian melakukan operasi pengambilan yang lebih sempit pada nilai baru.

Jadi, singkatnya, 'pada sistem endian kecil, gips adalah no-op.'


3
Dengan asumsi, tentu saja, byte tingkat tinggi yang tidak Anda baca dapat diabaikan (misalnya Anda tahu bahwa byte itu nol).
Steve314

10
@ Steve314: Jika saya di C downcasting dari 32 ke 16 bit (misalnya) pada sistem 2's-melengkapi - sebagian besar sistem - byte tidak perlu nol untuk diabaikan. Terlepas dari nilainya, saya dapat mengabaikannya dan tetap mematuhi standar C dan harapan programmer.

9
@ Stritzinger - kita sedang berbicara tentang kode perakitan / mesin yang dihasilkan oleh kompiler, yang tidak bisa portabel. Kode bahasa tingkat yang lebih tinggi untuk dikompilasi adalah portabel - ia hanya mengkompilasi ke operasi yang berbeda pada arsitektur yang berbeda (seperti semua ops lakukan).
bersamaan

7
Saya tidak membeli argumen ini, karena pada arsitektur big-endian, sebuah pointer bisa menunjuk ke akhir, daripada awal, dari apa pun yang Anda maksudkan dan daripada Anda akan memiliki keuntungan yang sama persis.
dan_waterworth

4
@dan_waterworth tidak cukup - ingat aturan aritmatika pointer di C, misalnya, dan apa yang terjadi ketika Anda menambah atau mengurangi gips dari pointer yang sama. Anda dapat memindahkan kompleksitas, tetapi Anda tidak bisa menghilangkannya.
jimwise

45

Saya selalu bertanya-tanya mengapa seseorang ingin menyimpan byte dalam urutan terbalik.

Big-endian dan little-endian hanya "tatanan normal" dan "tatanan terbalik" dari perspektif manusia, dan hanya jika semua ini benar ...

  1. Anda membaca nilai di layar atau di atas kertas.
  2. Anda meletakkan alamat memori yang lebih rendah di sebelah kiri, dan yang lebih tinggi di sebelah kanan.
  3. Anda sedang menulis dalam hex, dengan nybble orde tinggi di sebelah kiri, atau biner, dengan bit paling signifikan di sebelah kiri.
  4. Anda membaca dari kiri ke kanan.

Itu semua adalah konvensi manusia yang sama sekali tidak penting bagi CPU. Jika Anda mempertahankan # 1 dan # 2, dan membalik # 3, little-endian akan tampak "sangat alami" bagi orang-orang yang membaca bahasa Arab atau Ibrani, yang dituliskan dari kanan ke kiri.

Dan ada konvensi manusia lain yang membuat big-endian yang tampak tidak alami, seperti ...

  • Byte "lebih tinggi" (paling signifikan) harus di alamat memori "lebih tinggi".

Kembali ketika saya kebanyakan pemrograman 68K dan PowerPC, saya menganggap big-endian sebagai "benar" dan little-endian menjadi "salah". Tapi karena saya sudah melakukan lebih banyak pekerjaan ARM dan Intel, saya sudah terbiasa dengan little-endian. Itu benar-benar tidak masalah.


30
Angka-angka sebenarnya ditulis dari [digit paling signifikan] kiri ke [digit paling signifikan] kanan dalam bahasa Arab dan Ibrani.
Random832

5
Lalu mengapa bit dalam byte disimpan dalam format "big endian"? Kenapa tidak konsisten?
tskuzzy

11
Mereka tidak - bit 0 adalah konvensi yang paling tidak signifikan, dan bit 7 yang paling signifikan. Selain itu, Anda secara umum tidak dapat memesan bit dalam byte, karena bit tidak dapat dialamatkan secara individual. Tentu saja, mereka mungkin memiliki urutan fisik dalam protokol komunikasi atau media penyimpanan tertentu, tetapi kecuali jika Anda bekerja pada protokol tingkat rendah atau tingkat perangkat keras, Anda tidak perlu khawatir dengan pesanan ini.
Stewart

3
BlueRaja: hanya dengan konvensi penulisan di atas kertas. Ini tidak memiliki kesamaan dengan arsitektur CPU. Anda dapat menulis byte sebagai 0-7 LSB-MSB bukannya 7-0 MSB-LSB dan tidak ada perubahan dari sudut pandang algoritma.
SF.

2
@ SF: "Dorong pendek, pop apa pun kecuali pendek " akan membuat Anda terkejut. Bahkan jika Anda tidak merusak tumpukan dengan mendorong byte, Anda tidak pernah meletus atau sebaliknya ... x86 (32-bit), misalnya, benar - benar sangat ingin tumpukan disejajarkan dengan kata lain, dan mendorong atau menepuk apa pun yang menyebabkan stack pointer agar tidak kelipatan 4 dapat menyebabkan masalah penyelarasan. Dan bahkan jika tidak, semuanya mendorong seluruh kata / kata / qword / dll sekaligus - sehingga byte rendah masih akan menjadi yang pertama Anda dapatkan ketika Anda pop.
cao

41

OK, inilah alasannya karena saya sudah menjelaskannya kepada saya: Penambahan dan pengurangan

Ketika Anda menambah atau mengurangi angka multi-byte, Anda harus mulai dengan byte paling signifikan. Jika Anda menambahkan dua angka 16-bit misalnya, mungkin ada carry dari byte paling signifikan ke byte paling signifikan, jadi Anda harus mulai dengan byte paling signifikan untuk melihat apakah ada carry. Ini adalah alasan yang sama bahwa Anda mulai dengan digit paling kanan ketika melakukan penambahan dengan tangan. Anda tidak dapat memulai dari kiri.

Pertimbangkan sistem 8-bit yang mengambil byte secara berurutan dari memori. Jika ia mengambil byte paling signifikan pertama , ia dapat mulai melakukan penambahan sementara byte paling signifikan diambil dari memori. Paralelisme ini adalah mengapa kinerja lebih baik di endian kecil seperti pada sistem. Jika harus menunggu sampai kedua byte diambil dari memori, atau mengambilnya dalam urutan terbalik, itu akan memakan waktu lebih lama.

Ini pada sistem 8-bit lama. Pada CPU modern saya ragu urutan byte membuat perbedaan dan kami menggunakan sedikit endian hanya karena alasan historis.


3
Ah - jadi kira-kira alasan yang sama saya menggunakan chunk-little-endian pemesanan untuk bilangan bulat besar. Aku seharusnya menyelesaikannya. Orang-orang benar-benar perlu bekerja di dunia cyber sekarang - otak saya sudah sangat membutuhkan beberapa suku cadang dan beberapa peningkatan radikal, saya tidak bisa menunggu selamanya!
Steve314

2
Suatu pemikiran - 6502 tidak melakukan banyak matematika 16-bit dalam perangkat keras - itu, bagaimanapun, adalah prosesor 8 bit. Tapi itu memang melakukan pengalamatan relatif, menggunakan offset 8-bit yang ditandatangani relatif terhadap alamat basis 16-bit.
Steve314

2
Perhatikan bahwa ide ini masih penting untuk aritmatika integer multipel presisi (seperti yang dikatakan oleh Steve314), tetapi pada level kata. Sekarang, sebagian besar operasi tidak secara langsung dipengaruhi oleh endianness prosesor: seseorang masih dapat menyimpan kata paling tidak penting terlebih dahulu pada sistem big-endian, seperti yang dilakukan oleh GMP. Prosesor Little-endian masih memiliki keunggulan untuk beberapa operasi (misalnya beberapa konversi string?) Yang dapat lebih mudah dilakukan dengan membaca satu byte pada suatu waktu, karena hanya pada sistem little-endian, pemesanan byte dari angka-angka tersebut sudah benar.
vinc17

prosesor little-endian memiliki keuntungan jika bandwidth memori terbatas, seperti pada beberapa prosesor ARM 32-bit dengan bus memori 16-bit, atau 8088 dengan bus data 8-bit: prosesor hanya dapat memuat setengah rendah dan melakukan tambahkan / sub / mul ... dengan itu sambil menunggu setengah
phuclv yang

13

Dengan prosesor 8 bit itu tentu lebih efisien, Anda dapat melakukan operasi 8 atau 16bit tanpa perlu kode yang berbeda dan tanpa perlu buffer nilai-nilai tambahan.

Masih lebih baik untuk beberapa operasi tambahan jika Anda menangani byte pada suatu waktu.

Tetapi tidak ada alasan bahwa big-endian lebih alami - dalam bahasa Inggris Anda menggunakan tiga belas (little endian) dan dua puluh tiga (big endian)


1
Big-endian memang lebih mudah bagi manusia karena tidak perlu mengatur ulang byte. Sebagai contoh, pada PC, 0x12345678disimpan sebagai 78 56 34 12sedangkan pada sistem BE itu 12 34 56 78(byte 0 di sebelah kiri, byte 3 di sebelah kanan). Perhatikan bagaimana semakin besar angkanya (dalam hal bit), semakin banyak pertukaran yang dibutuhkan; sebuah KATA akan membutuhkan satu swap; DWORD, dua lintasan (tiga total swap); a QWORD three pass (7 total), dan seterusnya. Yaitu, (bits/8)-1swap. Pilihan lain adalah membacanya ke depan dan belakang (membaca setiap byte ke depan, tetapi memindai seluruh # ke belakang).
Synetech

Seratus-dan-tigabelas adalah endian-tengah, atau big-endian dengan "tiga belas" pada dasarnya satu digit non-desimal. Ketika kami menguraikan angka, ada beberapa penyimpangan kecil dari konvensi basis konstan yang kami gunakan untuk angka, tetapi begitu Anda menghapus kasus khusus itu sisanya adalah big-endian - jutaan sebelum ribuan, ribuan sebelum ratusan dll.
Steve314

@ Synetech- untungnya komputer tidak perlu peduli bagaimana manusia membacanya. Itu seperti mengklaim bahwa NAND flash lebih baik karena ot
Martin Beckett

1
@ Steve314, kata-kata angka yang dieja tidak penting, itu adalah pembacaan angka itulah yang kami gunakan saat kami memprogram. Martin, tidak ada komputer yang tidak perlu peduli bagaimana manusia membaca angka, tetapi jika mudah bagi manusia untuk membacanya, maka pemrograman (atau pekerjaan terkait lainnya) menjadi lebih mudah dan beberapa kekurangan dan bug dapat dikurangi atau dihindari.
Synetech

@ steve314 Dan dalam bahasa Denmark, "95" dilafalkan "fem halvfems" (lima, ditambah empat-dan-setengah-dua puluhan).
Vatine

7

Konvensi tanggal Jepang adalah "big endian" - yyyy / mm / dd. Ini berguna untuk menyortir algoritma, yang dapat menggunakan perbandingan-string sederhana dengan aturan karakter-pertama yang paling signifikan.

Sesuatu yang serupa berlaku untuk angka-angka big-endian yang disimpan dalam catatan bidang-paling-signifikan-pertama. Urutan signifikansi byte dalam bidang cocok dengan signifikansi bidang dalam catatan, sehingga Anda dapat menggunakan memcmpuntuk membandingkan catatan, tidak terlalu peduli apakah Anda membandingkan dua kata panjang, empat kata, atau delapan byte terpisah.

Balik urutan signifikansi bidang dan Anda mendapatkan keuntungan yang sama, tetapi untuk angka little-endian daripada big-endian.

Tentu saja ini memiliki signifikansi praktis yang sangat kecil. Apakah platform Anda big-endian atau little-endian, Anda dapat memesan bidang catatan untuk mengeksploitasi trik ini jika Anda benar-benar perlu. Hanya saja menyebalkan jika Anda perlu menulis kode portabel .

Saya mungkin juga menyertakan tautan ke banding klasik ...

http://tools.ietf.org/rfcmarkup?url=ftp://ftp.rfc-editor.org/in-notes/ien/ien137.txt

SUNTING

Pikiran ekstra. Saya pernah menulis perpustakaan integer besar (untuk melihat apakah saya bisa), dan untuk itu, potongan 32-bit disimpan dalam urutan little-endian, terlepas dari bagaimana platform memesan bit dalam potongan tersebut. Alasannya adalah ...

  1. Banyak algoritma yang secara alami mulai bekerja pada hasil yang paling tidak signifikan, dan ingin tujuan tersebut dicocokkan. Sebagai contoh sebagai tambahan, pembawa membawa lebih banyak dan lebih signifikan, sehingga masuk akal untuk memulai pada akhir yang paling tidak signifikan.

  2. Menumbuhkan atau mengecilkan nilai hanya berarti menambah / menghapus bongkahan di akhir - tidak perlu menggeser bongkahan ke atas / ke bawah. Menyalin mungkin masih diperlukan karena realokasi memori, tetapi tidak sering.

Ini tidak memiliki relevansi yang jelas dengan prosesor, tentu saja - sampai CPU dibuat dengan dukungan perangkat keras bilangan bulat besar, itu murni hal perpustakaan.


7

Tidak ada orang lain yang menjawab MENGAPA ini mungkin dilakukan, banyak hal tentang konsekuensi.

Pertimbangkan prosesor 8 bit yang dapat memuat satu byte dari memori dalam siklus clock yang diberikan.

Sekarang, jika Anda ingin memuat nilai 16 bit, ke (katakanlah) satu-satunya register 16 bit yang Anda miliki - yaitu penghitung program, maka cara sederhana untuk melakukannya adalah:

  • Muat satu byte dari lokasi pengambilan
  • menggeser byte ke kiri 8 tempat
  • memori kenaikan mengambil lokasi oleh 1
  • memuat byte berikutnya (ke bagian urutan rendah dari register)

hasilnya: Anda hanya perlu menambah lokasi pengambilan, Anda hanya memuat ke bagian urutan rendah dari register yang lebih luas, dan Anda hanya perlu dapat bergeser ke kiri. (Tentu saja, menggeser ke kanan sangat membantu untuk operasi lain sehingga yang satu ini merupakan sedikit tambahan.)

Konsekuensi dari ini adalah bahwa barang 16 bit (byte ganda) disimpan dalam urutan Most..Least. Yaitu, alamat yang lebih kecil memiliki byte paling signifikan - endian begitu besar.

Jika Anda mencoba memuat menggunakan endian kecil, Anda perlu memuat byte ke bagian bawah register lebar Anda, kemudian memuat byte berikutnya ke area pentahapan, menggesernya, dan kemudian memasukkannya ke bagian atas register yang lebih luas. . Atau gunakan pengaturan gating yang lebih kompleks untuk dapat memuat secara selektif ke byte atas atau bawah.

Hasil dari mencoba sedikit endian adalah Anda membutuhkan lebih banyak silikon (sakelar dan gerbang), atau lebih banyak operasi.

Dengan kata lain, dalam hal mendapatkan uang kembali di masa lalu, Anda mendapatkan lebih banyak pukulan untuk sebagian besar kinerja dan area silikon terkecil.

Hari-hari ini, pertimbangan-pertimbangan ini dan cukup banyak tidak relevan, tetapi hal-hal seperti mengisi pipa mungkin masih sedikit masalah besar.

Ketika datang untuk menulis s / w, hidup sering lebih mudah ketika menggunakan pengalamatan endian kecil.

(Dan prosesor big endian cenderung menjadi big endian dalam hal pemesanan byte dan sedikit endian dalam hal bit-in-bytes. Tetapi beberapa prosesor aneh dan akan menggunakan pemesanan bit endian besar serta pemesanan byte. Ini membuat hidup sangat menarik untuk perancang h / w menambahkan periferal yang dipetakan memori tetapi tidak ada konsekuensi lain bagi programmer.)


3

jimwise membuat poin yang bagus. Ada masalah lain, di little endian Anda dapat melakukan hal berikut:

byte data[4];
int num=0;
for(i=0;i<4;i++)
    num += data[i]<<i*8; 

OR 

num = *(int*)&data; //is interpreted as

mov dword data, num ;or something similar it has been some time

Lebih lurus ke depan untuk programmer yang tidak terpengaruh oleh kerugian nyata dari lokasi yang ditukar dalam memori. Saya pribadi menemukan endian besar untuk menjadi kebalikan dari apa yang alami :). 12 harus disimpan dan ditulis sebagai 21 :)


1
Ini hanya membuktikan bahwa lebih cepat / lebih mudah untuk bekerja dalam format apa pun yang asli untuk CPU. Itu tidak mengatakan apa-apa tentang apakah itu lebih baik. Hal yang sama berlaku untuk big endian: for(i=0; i<4; i++) { num += data[i] << (24 - i * 8); }sesuai dengan move.l data, numpada CPU big endian.
Martin Vilcans

@martin: kurang satu pengurangan lebih baik dalam buku saya
Cem Kalyoncu

Tidak masalah karena kompiler akan tetap membuka gulungannya. Bagaimanapun, banyak CPU memiliki instruksi swapping byte untuk menangani masalah ini.
Martin Vilcans

saya tidak setuju karena pada big endian, saya akan melakukan {num << = 8; num | = data [i]; } setidaknya ini tidak harus menghitung hitungan shift kiri menggunakan mul
Hayri Uğur Koltuk

@ali: kode Anda akan melakukan operasi persis yang saya tulis dan tidak akan bekerja pada big endian.
Cem Kalyoncu

1

Saya selalu bertanya-tanya mengapa seseorang ingin menyimpan byte dalam urutan terbalik

Angka desimal ditulis big endian. Juga bagaimana Anda menulisnya dalam bahasa Inggris. Anda mulai dengan digit paling signifikan dan berikutnya paling signifikan ke paling tidak signifikan. misalnya

1234

adalah seribu dua ratus tiga puluh empat.

Inilah cara big endian kadang-kadang disebut tatanan alam.

Dalam endian kecil, jumlah ini adalah satu, dua puluh, tiga ratus empat ribu.

Namun, ketika Anda melakukan aritmatika seperti penjumlahan atau pengurangan, Anda mulai dengan bagian akhir.

  1234
+ 0567
  ====

Anda mulai dengan 4 dan 7, tulis angka terendah dan ingat carry. Kemudian Anda menambahkan 3 dan 6 dll. Untuk menambah, mengurangi atau membandingkan, lebih mudah diterapkan, jika Anda sudah memiliki logika untuk membaca memori secara berurutan, jika angkanya terbalik.

Untuk mendukung big endian dengan cara ini, Anda perlu logika untuk membaca memori secara terbalik, atau Anda memiliki proses RISC yang hanya beroperasi pada register. ;)

Banyak dari desain Intel x86 / Amd x64 adalah historis.


0

Big-endian berguna untuk beberapa operasi (perbandingan "bignum" pegas dengan panjang oktet yang sama dengan pikiran). Little-endian untuk orang lain (menambahkan dua "bignum", mungkin). Pada akhirnya, itu tergantung pada apa perangkat keras CPU telah diatur, biasanya satu atau yang lain (beberapa chip MIPS, IIRC, switchable saat boot menjadi LE atau BE).


0

Ketika hanya penyimpanan dan transfer dengan panjang variabel yang terlibat, tetapi tidak ada aritmatika dengan nilai berganda, maka LE biasanya lebih mudah untuk ditulis, sedangkan BE lebih mudah dibaca.

Mari kita ambil konversi int-to-string (dan kembali) sebagai contoh khusus.

int val_int = 841;
char val_str[] = "841";

Ketika int dikonversi ke string, maka digit paling signifikan lebih mudah untuk diekstraksi daripada digit paling signifikan. Itu semua dapat dilakukan dalam satu loop sederhana dengan kondisi ujung yang sederhana.

val_int = 841;
// Make sure that val_str is large enough.

i = 0;
do // Write at least one digit to care for val_int == 0
{
    // Constants, can be optimized by compiler.
    val_str[i] = '0' + val_int % 10;
    val_int /= 10;
    i++;
}
while (val_int != 0);

val_str[i] = '\0';
// val_str is now in LE "148"
// i is the length of the result without termination, can be used to reverse it

Sekarang coba yang sama dalam urutan BE. Biasanya Anda membutuhkan pembagi lain yang memiliki kekuatan 10 terbesar untuk nomor tertentu (di sini 100). Anda pertama-tama harus menemukan ini, tentu saja. Banyak hal yang harus dilakukan.

Konversi string ke int lebih mudah dilakukan di BE, ketika dilakukan sebagai operasi penulisan balik. Tuliskan menyimpan angka paling signifikan yang terakhir, jadi harus dibaca terlebih dahulu.

val_int = 0;
length = strlen(val_str);

for (i = 0; i < length; i++)
{
    // Again a simple constant that can be optimized.
    val_int = 10*val_int + (val_str[i] - '0');
}

Sekarang lakukan hal yang sama dalam urutan LE. Sekali lagi, Anda memerlukan faktor tambahan yang dimulai dengan 1 dan dikalikan dengan 10 untuk setiap digit.

Jadi saya biasanya lebih suka menggunakan BE untuk penyimpanan, karena nilai ditulis tepat sekali, tetapi membaca setidaknya sekali dan mungkin berkali-kali. Untuk strukturnya yang lebih sederhana, saya biasanya juga pergi rute untuk mengkonversi ke LE dan kemudian membalikkan hasilnya, bahkan jika itu menulis nilai untuk kedua kalinya.

Contoh lain untuk penyimpanan BE adalah pengkodean UTF-8, dan banyak lagi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.