Küçük endian formatının avantajı nedir?


140

Intel işlemciler (ve belki bazıları da) depolama için küçük endian biçimini kullanır.

Her zaman birisinin neden baytları ters sırayla saklamak istediğini merak ediyorum. Bu formatın büyük endian formatına göre herhangi bir avantajı var mı?


1
6502 bir erken (ilk?) Boru hattı işlemciydi. Boru hattı nedeniyle performansla ilgili bir sorun için çok az-kuşçu olduğu yönündeki iddiaları hatırlıyor gibiyim - ama şimdi bu sorunun ne olabileceği hakkında hiçbir fikrim yok. Baska öneri?
Steve314

1
@ Steve314: Cevabım, endian'ın boru hattı olan bir CPU'daki performansa nasıl yardımcı olduğunu açıklıyor: programmers.stackexchange.com/q/95854/27874
Martin Vilcans

3
Küçük endian, büyük endian - birini veya diğerini seçmelisin. Yolun solunda veya sağında sürmek gibi.

3
ASM'de, tercihen 6502 veya Z80 gibi bir "eski okul" mimarisi için bazı kodlar yazmanızı öneririm. Bunların neden küçük endian kullandığını hemen göreceksiniz. Büyük endian kullanan mimariler, bu biçimi tercih eden kılan komut setlerinde belirli özelliklere sahiptir. Bu keyfi bir karar değil!
Stefan Paul Noack

2
Her bayt sıralı sistemin kendi avantajları vardır. Küçük endian makineleri, diğerlerini okumadan önce en düşük baytı okumanızı sağlar. Bir sayının tek mi yoksa çift mi (son bit 0) çok kolay olup olmadığını kontrol edebilirsiniz. Büyük-endian sistemleri verileri hafızada saklar, insanların düşündüğü gibi (soldan sağa), bu da düşük seviye hata ayıklamayı kolaylaştırır.
Koray Tugay

Yanıtlar:


198

Her iki şekilde de argümanlar var, ancak bir nokta, küçük endian sisteminde, 32, 16 veya 8 bit genişliğinde alınan bellekteki belirli bir değerin adresinin aynı olmasıdır.

Başka bir deyişle, bellekte iki baytlık bir değer varsa:

0x00f0   16
0x00f1    0

'16' değerini 16 bitlik bir değer olarak (çoğu 32 bit sistemde c 'kısa') veya 8 bitlik bir değer olarak (genellikle c 'char') almak yalnızca kullandığınız getirme talimatını değiştirir - aldığınız adresi değil dan.

Büyük bir endian sisteminde, yukarıdaki gibi düzenlenmiştir:

0x00f0    0
0x00f1   16

işaretçiyi artırmanız ve ardından yeni değerde daha dar alma işlemi gerçekleştirmeniz gerekir.

Yani, kısacası, 'küçük endian sistemlerinde, yayınlar işlemez.'


3
Elbette, okumadığınız yüksek sıralı baytların dikkate alınmayacağını varsayarsak (örneğin, zaten sıfır olduğunu biliyorsunuzdur).
Steve314

10
@ Steve314: Eğer 2'nin tamamlayıcı bir sistemde 32 - 16 bit (örn.) Altında bir C - kapalı yayın yapıyorsam - sistemlerin büyük çoğunluğu - baytların göz ardı edilmesi için sıfır olması gerekmez. Değerleri ne olursa olsun, onları görmezden gelebilir ve C standardı ve programcı beklentileri ile uyumlu kalabilirim.

9
@Stritzinger - Bir derleyici tarafından üretilen, taşınabilir olmayan derleme / makine kodundan bahsediyoruz. Derlenecek daha üst seviyedeki dil kodu taşınabilirdir - sadece farklı mimarilerdeki farklı işlemleri derler (tüm seçmenlerin yaptığı gibi).
jimwise

7
Bu argümanı satın almıyorum, çünkü büyük-endian mimarilerinde, bir işaretçi, atıfta bulunduğunuz her şeyin başlangıcından ziyade, tam olarak aynı avantaja sahip olduğunuzu gösterebilir.
dan_waterworth

4
@ dan_waterworth tam olarak değil - örneğin C'deki işaretçi aritmetik kurallarını ve aynı işaretleyicinin atma ya da düşürme zamanlarında ne olacağını unutmayın. Karmaşıklığı taşıyabilirsiniz, ancak ortadan kaldıramazsınız.
jimwise

45

Her zaman birisinin neden baytları ters sırayla saklamak istediğini merak ediyorum.

Büyük-endian ve küçük-endian, insan bakış açısına göre sadece "normal sıra" ve "ters sıra" dır ve daha sonra bunların hepsi doğruysa ...

  1. Ekrandaki veya kağıttaki değerleri okuyorsunuz.
  2. Düşük bellek adreslerini sola, yüksek adresleri sağa koyarsınız.
  3. Solda yüksek dereceli nybble, solda en belirgin bit olan binary ile onaltılı olarak yazıyorsunuz.
  4. Soldan sağa okuyorsun.

Bunların hepsi bir CPU için hiç önemi olmayan insan sözleşmeleridir. # 1 ve # 2'yi elinde tutup 3'ü çevirirseniz, küçük endian, Arapça veya İbranice okuyan ve sağdan sola yazılan insanlara "tamamen doğal" görünür.

Ve doğal olmayan görünen büyük-endian yapan başka insan sözleşmeleri var.

  • "Yüksek" (en anlamlı) bayt, "yüksek" bellek adresinde olmalıdır.

Çoğunlukla 68K ve PowerPC'yi programlarken büyük-endian'ın "doğru" ve küçük-endian'ın "yanlış" olduğunu düşündüm. Fakat daha fazla ARM ve Intel çalışması yaptığım için, küçük endianlara alışmıştım. Gerçekten önemli değil.


30
Sayılar aslında Arapça ve İbranice'de [en önemli rakam] soldan [en az önemli rakam] sağına yazılır.
Random832

5
Öyleyse neden bir bayt içindeki bitler "büyük endian" formatında saklanıyor? Neden tutarlı olmuyorsun?
tskuzzy

11
Bit 0 değil, kongre gereği en az anlamlı, bit 7 ise en önemliler. Dahası, bitler ayrı ayrı adreslenemediğinden genellikle bir bayt içindeki bitler için sipariş veremezsiniz. Elbette, belirli bir iletişim protokolünde veya depolama ortamında fiziksel bir düzenleri olabilir, ancak düşük seviye protokolde veya donanım düzeyinde çalışmadığınız sürece, bu siparişle ilgili endişelenmenize gerek yoktur.
Stewart

3
BlueRaja: sadece kağıda yazı sözleşmesi ile. Bunun CPU mimarisi ile hiçbir ortak yanı yoktur. Baytı 7-0 MSB-LSB yerine 0-7 LSB-MSB olarak yazabilirsiniz ve algoritma bakış açısından hiçbir şey değişmez.
SF.

2
@SF .: "Kısa bas, kısa ama her şeyi patlat " her halükarda sana bir sürpriz verecek. Eğer pop ya da tam tersi ... x86 (32-bit) asla bayt iterek yığını bozulmasını almıyorsanız bile, örneğin, gerçekten gerçekten yığın-dword hizalanmış ve itme veya neden bir şey haşhaş olmak istiyor yığın göstergesinin 4 katı olmadığından hizalama sorunlarına neden olabilir. Olmasa bile, eşyalar bir seferde tam bir kelime / dword / qword / etc itti - yani düşük bayt, pop açtığınızda ilk aldığınız kelime olacak.
cHao

41

Tamam, işte bana açıklamamın nedeni: Toplama ve çıkarma

Çok baytlı sayıları topladığınızda veya çıkardığınızda, en az anlamlı baytla başlamanız gerekir. Örneğin, iki adet 16 bitlik bir sayı ekliyorsanız, en az anlamlı bayttan en anlamlı bayta kadar bir taşıma olabilir, bu nedenle bir taşıma olup olmadığını görmek için en az anlamlı byte ile başlamanız gerekir. Bu, el yazısı eklemesi yaparken en sağdaki rakamla başlamanızın nedenidir. Soldan başlayamazsın.

Bellekten sırayla bayt alan 8 bit bir sistem düşünün. O en düşük değerli baytı getirir Eğer ilk , bu ek yaparak başlayabilirsiniz ise en önemli byte bellekten alınıyor. Bu paralellik, performansın sistem gibi küçük çetelerde daha iyi olmasının nedenidir. Her iki bayt da bellekten alınana kadar beklemek ya da bunları ters sırada almak zorunda kalırsa daha uzun sürer.

Bu eski 8-bit sistemlerde. Modern bir CPU'da bayt sırasının herhangi bir fark yarattığından şüpheliyim ve sadece tarihsel nedenlerden dolayı küçük endian kullanıyoruz.


3
Ah - bu yüzden büyük tamsayılar için küçük endian öbek siparişi kullanmamın nedeni aynı. Bunu çözmeliydim. İnsanların şimdi sibernetik üzerinde çalışmaya gerçekten ihtiyacı var - beynimin zaten bazı yedek parçalara ve radikal yükseltmelere ihtiyacı var, sonsuza dek bekleyemem!
Steve314

2
Bir düşünce - 6502 donanımda 16-bit matematik yapmadı - sonuçta 8 bitlik bir işlemciydi. Ama yaptığı bir 16 bit taban adresine bağıl 8 bitlik imzalı uzaklıklar kullanılarak, göreli adresleme yapmak.
Steve314

2
Bu fikrin hala çoklu hassasiyet tamsayı aritmetiği için önemli olduğunu unutmayın (Steve314 tarafından söylendiği gibi), ancak kelime düzeyinde. Şimdi, çoğu işlem doğrudan işlemcinin türlülüğünden etkilenmiyor: bir kişi hala en az önemli sözcüğü ilk önce GMP'nin yaptığı gibi büyük-büyük bir sistemde depolayabilir. Küçük-endian işlemcileri, bir seferde bir byte okuyarak kolayca yapılabilecek birkaç işlem için (örneğin, bazı string dönüşümleri?) Hala bir avantaja sahiptir, çünkü sadece küçük bir endian sisteminde, bu sayıların byte sıralaması doğrudur.
vinc17

little-endian işlemcileri, 16-bit bellek veriyoluna sahip 32-bit ARM işlemcileri veya 8-bit veri yoluna sahip 8088: bellek bant genişliğinin sınırlı olması durumunda bir avantaja sahiptir. add / sub / mul ... yüksek yarısını beklerken onunla
phuclv

13

8 bit işlemcileri ile kesinlikle daha verimli oldu, farklı bir koda gerek duymadan ve ekstra değerleri tamponlamaya gerek kalmadan 8 veya 16 bitlik bir işlem gerçekleştirebilirsiniz.

Her seferinde bir bayt satıyorsanız, bazı ek işlemler için hala daha iyidir.

Ancak büyük endian'ın daha doğal olması için hiçbir neden yoktur - İngilizce'de on üç (küçük endian) ve yirmi üç (büyük endian) kullanıyorsunuz


1
Big-endian, insanlar için gerçekten daha kolaydır, çünkü baytların yeniden düzenlenmesini gerektirmez. Örneğin, bir PC'de, bir BE sisteminde olduğu 0x12345678gibi depolanır (bayt 0 solda, bayt 3 sağdadır). Sayının ne kadar büyük olduğunu (bit cinsinden) ne kadar büyükse o kadar fazla gerektirir; Bir WORD bir takas gerektirir; bir DWORD, iki geçiş (toplam üç adet swap); bir QWORD üç geçişi (toplam 7), vb. Yani, takas. Başka bir seçenek ikisini de ileriye okuyor ve geriye (her bayt ileri okuma, ancak geriye bütün # tarayarak). 78 56 34 1212 34 56 78(bits/8)-1
Synetech

Yüz on üç, ya orta-endian, ya da "on üç" esasen ondalık olmayan bir rakam olan büyük endiandır. Rakamları hecelediğimizde, rakamlar için kullandığımız sabit temelli sözleşmelerden bazı küçük sapmalar vardır, ancak bir kez bu özel durumları çıkardığınızda geri kalanlar büyük-
endian'dır

@ Synetech- Neyse ki bilgisayarın insanların onları nasıl okuduğu ile ilgilenmesi gerekmez. Bu NAND flaşının daha iyi olduğunu iddia etmek gibi bir şey çünkü ot '
Martin Beckett

1
@ Steve314, sayıların hecelenen kelimeleri önemli değil, programlanırken kullandığımız sayısal okuma. Martin, hiçbir bilgisayar insanların sayıları nasıl okuduğu ile ilgilenmek zorunda değildir, ancak insanların bunları okuması kolaysa, programlama (veya diğer ilgili işler) daha kolay hale gelir ve bazı kusurlar ve hatalar azaltılabilir veya önlenebilir.
Synetech

@ steve314 Danimarka'da "95" "fem halvfems" (beş, artı dört buçuk yirmili) olarak telaffuz edildi.
Vatine

7

Japon tarih konvansiyonu "büyük endian" - yyyy / mm / gg. Bu, normal ilk karakter olan en önemli kural olan basit bir dize karşılaştırmasını kullanabilen algoritmaları sıralamak için kullanışlıdır.

Benzer bir şey, en önemli alan-ilk kaydında saklanan büyük-endian numaraları için de geçerlidir. Alanlardaki baytların önem sırası, kayıt içindeki alanların önemi ile eşleşir; bu nedenle memcmp, iki uzun kod, dört sözcük veya sekiz ayrı bayt karşılaştırmanıza bakılmaksızın bir kayda değer kullanabilirsiniz .

Alanların önem sırasını çevirin ve aynı avantajı elde edin, ancak büyük endian yerine küçük endian sayıları için.

Bunun elbette çok az pratik önemi var. Platformunuz büyük veya küçük endian olsa da, gerçekten ihtiyacınız varsa bu numaradan yararlanmanız için bir kayıt alanı sipariş edebilirsiniz. Taşınabilir kod yazmanız gerekirse, sadece bir acıdır .

Klasik itiraz için bir link de ekleyebilirim ...

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

DÜZENLE

Ekstra bir düşünce. Bir keresinde büyük bir tamsayı kütüphanesi yazdım (görebiliyor muyum görmek için) ve bunun için, 32-bitlik geniş parçalar platformun bu parçalardaki bitleri nasıl sıraladığından bağımsız olarak küçük-endian düzende saklanır. Sebepler ...

  1. Birçok algoritma doğal olarak en az kayda değer uçta çalışmaya başlar ve bu uçların eşleşmesini ister. Örneğin, ek olarak, taşıyıcılar giderek daha fazla önemli haneye yayılmaktadır, bu nedenle en az anlamlı uçtan başlamak mantıklıdır.

  2. Bir değeri büyütmek veya küçültmek, yalnızca parçaların toplanması / kaldırılması anlamına gelir - parçaların yukarı / aşağı kaydırılması gerekmez. Belleğin yeniden konumlandırılması nedeniyle kopyalama işlemi hala gerekli olabilir, ancak sık sık değil.

Bunun elbette işlemcilerle ilgisi yok - elbette - CPU'lar donanım tamsayılı desteği ile yapılıncaya kadar, tamamen bir kütüphane meselesi.


7

Bunun yapılabileceği NEDEN başka hiç kimse cevap vermedi, sonuçları hakkında çok şey var.

Belirli bir saat döngüsünde bellekten tek bir bayt yükleyebilen 8 bit bir işlemci düşünün.

Şimdi, eğer 16 bitlik bir değere sahip olmak istiyorsanız, sahip olduğunuz tek ve tek 16 bitlik kasaya (örneğin, program sayacı), o zaman bunu yapmanın basit bir yolu:

  • Getirme konumundan bir bayt yükleme
  • bu baytı sola 8 konuma kaydır
  • 1 ile artış hafızası alma konumu
  • Bir sonraki baytı yükle (kasanın düşük dereceli bölümüne)

sonuç: yalnızca alma konumunu artırırsınız, yalnızca daha geniş kayıt listenizin düşük dereceli bölümüne yüklersiniz ve yalnızca sola kaydırmanız gerekir. (Tabii ki, sağa kaydırmak diğer işlemler için yararlıdır, bu yüzden bu bir yan gösteri birazdır.)

Bunun bir sonucu olarak, 16 bitlik (çift baytlık) öğelerin Most sırayla saklanmasıdır. Yani, küçük adres en önemli bayta sahiptir - çok büyük endian.

Bunun yerine küçük endian kullanarak yüklemeyi denediyseniz, geniş yazıcınızın alt kısmına bir bayt yüklemeniz, ardından bir sonraki baytı bir hazırlama alanına yüklemeniz, kaydırmanız ve daha sonra geniş yazıcınızın üst kısmına yerleştirmeniz gerekir. . Veya seçici olarak üst veya alt byte'a yükleyebilmek için daha karmaşık bir düzenleme düzenini kullanın.

Küçük endian'a gitmeye çalışmanın sonucu ya daha fazla silikona (anahtarlar ve kapılar) ya da daha fazla operasyona ihtiyaç duymanızdır.

Başka bir deyişle, eski günlerde paranın karşılığını alma konusunda, çoğu performans ve en küçük silikon alanı için daha fazla patlama elde ettiniz.

Bu günlerde, bu düşünceler ve hemen hemen alakasız, ancak boru hattı dolgusu gibi şeyler hala büyük bir sorun olabilir .

S / w yazma söz konusu olduğunda, küçük endian adresleme kullanıldığında hayat sıklıkla daha kolaydır.

(Ve büyük endian işlemciler bit-in-bayt cinsinden bayt sıralaması ve küçük endian açısından büyük endian olma eğilimindedirler. Ancak bazı işlemciler garip ve bayt sıralaması yanı sıra sipariş büyük endian bit kullanacaktır. Bu hayat yapar çok Bellek eşlemeli çevre birimleri ekleyen salak tasarımcı için ilginç ancak programcının başka bir sonucu yok.)


3

jimwise iyi bir noktaya değindi. Başka bir sorun var, küçük endian'da şunları yapabilirsiniz:

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

Hafızadaki yer değiştirilen yerlerin bariz dezavantajından etkilenmeyen programcılar için daha yalındır. Şahsen ben doğal olanın tersi olan büyük endian buluyorum :). 12 21 gibi kaydedilmeli ve yazılmalıdır :)


1
Bu sadece CPU için doğal olan formatta çalışmanın daha hızlı / kolay olduğunu kanıtlar. Daha iyi olup olmadığı hakkında hiçbir şey söylemiyor. Aynı şey büyük endian için de geçerli: büyük bir endian CPU'ya for(i=0; i<4; i++) { num += data[i] << (24 - i * 8); }karşılık geliyor move.l data, num.
Martin Vilcans

@martin: bir daha az çıkarma kitabımda daha iyi
Cem Kalyoncu

Derleyicinin yine de döngüyü çözmesi gerçekten önemli değil. Her durumda, birçok CPU bu sorunu ele almak için talimatları değiştirme byte var.
Martin Vilcans

büyük endian bcoz katılıyorum, ben yapardım {num << = 8; num | = veri [i]; } en azından bu, mul kullanarak sola kaydırma sayımını hesaplamak zorunda değildir
Hayri Uğur Koltuk

@ali: Kodunuz yazdığım işlemi yapacak ve endian üzerinde çalışmayacak.
Cem Kalyoncu

1

Her zaman birisinin neden baytları ters sırada depolamak istediğini merak ediyorum.

Ondalık sayı büyük endian ile yazılmıştır. Aynı zamanda İngilizce dilinde nasıl yazdığınız, en önemli rakamla, en önemlisi de en önemlisi olanı ile başlarsınız. Örneğin

1234

bin, iki yüz otuz dört.

Bu şekilde büyük endian bazen doğal düzen denir.

Küçük endian'da, bu sayı bir, yirmi, üç yüz dört bin olur.

Bununla birlikte, toplama veya çıkarma gibi aritmetik işlem yaptığınızda, bitişle başlarsınız.

  1234
+ 0567
  ====

4 ve 7 ile başlarsınız, en düşük rakamı yazıp taşımayı hatırlayın. Sonra 3 ve 6 vb. Eklersiniz. Toplamak, çıkarmak veya karşılaştırmak için, eğer sayıları tersine çevirirseniz, hafızayı sırayla okumak için mantık varsa, uygulanması daha kolaydır.

Büyük endian'ı bu şekilde desteklemek için, belleği tersten okuyabilmek için mantığa ihtiyacınız var, ya da sadece kayıtlar üzerinde çalışan RISC işleminiz var. ;)

Intel x86 / Amd x64 tasarımının çoğu tarihidir.


0

Big-endian bazı işlemler için kullanışlıdır (eşit oktet uzunluktaki yayların "bignumlarının" karşılaştırılması). Diğerleri için Little-endian (muhtemelen iki "bignum" ekleyerek). Sonunda, CPU donanımının ne için kurulduğuna bağlı, genellikle bir veya diğeri (bazı MIPS yongaları IIRC, önyüklemede LE veya BE olacak şekilde değiştirilebilir).


0

Yalnızca değişken uzunluklarda depolama ve aktarma söz konusu olduğunda, ancak birden fazla değere sahip hiçbir aritmetik olmadığında, LE'nin yazması genellikle kolaydır, BE'nin okunması daha kolaydır.

Belirli bir örnek olarak bir dizgeden int'ye dönüşüm (ve geri) alalım.

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

İnt dizgeye dönüştürüldüğünde, en az anlamlı olan rakam, en önemli olan rakamdan daha kolaydır. Hepsi basit bir son koşul ile basit bir döngüde yapılabilir.

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

Şimdi aynısını BE sırayla deneyin. Genellikle, belirli bir sayı için 10'un en büyük gücüne sahip başka bir bölene ihtiyacınız vardır (burada 100). İlk önce bunu bulman gerek, elbette. Yapacak daha çok şey var.

İnt dönüştürme dizesi, ters yazma işlemi olarak yapıldığında, BE'de yapmak daha kolaydır. Yazma en son haneyi depolar, bu yüzden ilk önce okunması gerekir.

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');
}

Şimdi aynısını LE sırasına göre yapın. Yine, 1 ile başlayan ve her hane için 10 ile çarpılan ek bir faktöre ihtiyacınız olacaktır.

Bu yüzden genellikle BE'yi depolamak için kullanmayı tercih ederim, çünkü bir değer tam olarak bir kez yazılır, ancak en az bir kez ve belki de birçok kez okunur. Daha basit yapısı için, genellikle LE'ye dönüştürme yolunu izlerim ve sonra değeri ikinci kez yazsa bile sonucu tersine çeviririm.

BE depolama için başka bir örnek UTF-8 kodlaması ve daha pek çoğu olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.