Bit kaydırma endianiteye bağlı mı?


156

Diyelim ki 'numb'=1025 [00000000 00000000 00000100 00000001]temsil edilen numara var :

Little-Endian Makinede:

00000001 00000100 00000000 00000000

Big-Endian Makinede:

00000000 00000000 00000100 00000001

Şimdi, 10 bitlik Sol Shift uygularsam (yani: numb << = 10), sahip olmalıyım:

[A] Little-Endian Makinasında:

GDB'de fark ettiğim gibi, Little Endian Sol Vardiyayı 3 adımda yapıyor: [Sadece işlemi daha iyi anlamak için '3' Adım gösterdim]

  1. Hayır tedavi. Big-Endian Sözleşmesinde:

    00000000        00000000        00000100    00000001
  2. Sola Kaydırma Uygula:

    00000000        00010000        00000100        00000000
  3. Sonucu Little-Endian'da tekrar temsil edin:

    00000000        00000100        00010000        00000000 

[B]. Big-Endian Makinede:

00000000        00010000        00000100        00000000

Benim sorum:

Küçük Endian Konvansiyonuna doğrudan Sol Vardiya uygularsam, şunları vermelidir:

numb:

00000001 00000100 00000000 00000000

numb << 10:

00010000 00000000 00000000 00000000

Ama aslında şunu veriyor:

00000000        00000100        00010000        00000000 

Sadece ikinci sonucu elde etmek için, yukarıda üç varsayımsal adım gösterdim.

Lütfen yukarıdaki iki sonucun neden farklı olduğunu açıklayın: asıl sonucu numb << 10beklenen sonuçtan farklı.

Yanıtlar:


194

Endianness, değerlerin hafızada saklanma şeklidir. İşlemciye yüklendiğinde, endianiteye bakılmaksızın, bit kaydırma talimatı işlemci kaydındaki değer üzerinde çalışır. Bu nedenle, bellekten işlemciye yükleme, büyük endian'a dönüştürmeye eşdeğerdir, kaydırma işlemi sonra gelir ve daha sonra yeni değer, küçük endian bayt sırasının yeniden yürürlüğe girdiği bellekte saklanır.

Güncelleme, @jww sayesinde: PowerPC'de vektör kaymaları ve dönüşleri endian duyarlıdır. Bir vektör kaydında bir değere sahip olabilirsiniz ve bir kaydırma küçük-endian ve big-endian üzerinde farklı sonuçlar üretir .


4
Açıklama için teşekkürler. Lütfen bu tür karışıklıkları daha iyi anlayabileceğim bazı referanslar önerebilir misiniz?
Sandeep Singh

4
Endianlığı anlamak için en iyi şey, onu gömülü bir düzeyde farklı mimarilerde kullanmaktır. Ancak, sizi şu iki makaleye yönlendirebilirim: codeproject.com/KB/cpp/endianness.aspx ve ibm.com/developerworks/aix/library/au-endianc/…
Carl

3
Yani benim kod endian ne olursa olsun çalışır ?! bu harika! Cehenneme geri dönmek için kodumu kesmek zorunda kalacağımdan çok endişelendim!
MarcusJ

2
@MarcusJ: Mutlaka değil. Örneğin, 32 bit tamsayıyı temsil eden bir dosyadan 4 bayt okuyorsanız, düzgün bir şekilde yorumlamak için verileri alan sistemin endianitesiyle birlikte okuduğunuz verilerin endianitesini göz önünde bulundurmanız gerekir. veri.
Carl

3
PowerPC'de vektör kaymaları ve dönüşleri endian duyarlıdır. Bir vektör kaydında bir değere sahip olabilirsiniz ve bir kaydırma küçük-endian ve big-endian üzerinde farklı sonuçlar üretir.
jww

58

Hayır, bitshift, C'nin diğer herhangi bir kısmı gibi, temsiller değil , değerler olarak tanımlanır . 1 ile sola kaydırma 2 ile çarpma, sağa kaydırma bölünme. (Her zaman olduğu gibi bitsel işlemler kullanılırken, imzaya dikkat edin. Her şey imzasız integral türleri için en iyi tanımlanmıştır.)


1
Bu temel olarak tamsayı aritmetiği için doğrudur, ancak C, temsile bağlı davranış için birçok durum sağlar.
Edmund

2
@Edmund: Hm ... en önemlisi, imzanın uygulanması belirtilmedi ve sonuç olarak, bitsel işlemlerin (sağa kaydırma gibi) ve modulo ve bölmenin davranışı, negatif tamsayılarda tanımlanan uygulamalardır. Aklınızda, uygulama tanımlı başka neler var?
Kerrek SB

@KerrekSB maalesef negatif tamsayılarda tanımlanan uygulama değildir. C89'da belirtilmemiş ve C99 + 'da tanımlanmamıştır, bu çok kötü bir fikirdi.
Paolo Bonzini

@PaoloBonzini: Evet, iyi bir nokta. Aslında bu daha da iyidir, çünkü vardiya işlemlerinin değerler açısından tanımlandığı, muhtemelen sonuç temsil edilemediğinde tanımsız olduğu ve altta yatan temsil hakkında spekülasyon yapılmasının yardımcı olmadığı noktasını güçlendirir.
Kerrek SB

@KerrekSB: Mesele şu ki, duruma göre herkesin hem değerler hem de temsil olarak temsil edilmesi için sol vardiyaya ihtiyacı var. İmzasız tamsayıların kullanılması başka sorunlara neden olabilir, örneğin 64 bit ve 32 bit x &= -1u << 20ise büyük olasılıkla yanlış olur . Bu nedenle GCC, imzalı vardiyalara asla tanımlanmamış veya hatta belirtilmemiş olarak davranmaya söz vermemektedir. xint
Paolo Bonzini

5

Hangi vites değiştirme talimatı ilk önce üst sıradaki bitleri değiştirirse, sol kaydırma kabul edilir. Hangi vites değiştirme talimatı önce düşük dereceli bitleri değiştirirse, doğru kaydırma olarak kabul edilir. Bu anlamda, davranışı >>ve <<için unsignednumaralar endian bağlı olmayacaktır.


4

Bilgisayarlar sayıları bizim yaptığımız gibi yazmazlar. Değer basitçe değişir. Bayt-byte-byte'a bakmak konusunda ısrar ederseniz (bilgisayarın böyle yapmadığı halde), küçük endian bir makinede, ilk bayt sola kayıyor, fazla bitler ikinci bayta gidiyor, ve bunun gibi.

(Bu arada, baytları yatay olarak değil dikey olarak yazarsanız, daha yüksek adresleri üstte olacak şekilde yazıyorsanız, daha az mantıklıdır. Bellek haritası diyagramları genellikle bu şekilde çizilir.)


2

Kabul edilen cevap, endianess'in hafıza görünümünden bir kavram olduğuna işaret ediyor. Ama bunun doğrudan soruyu cevapladığını sanmıyorum.

Bazı cevaplar bana bitsel işlemlerin endianess'e bağlı olmadığını ve işlemcinin baytları başka bir şekilde temsil edebileceğini söylüyor . Her neyse, bu endianess'in soyutlanmasından bahsediyor.

Ancak, örneğin kağıt üzerinde bitsel hesaplamalar yaptığımızda, ilk etapta endianiliği belirtmeniz gerekmez mi? Çoğu zaman örtük olarak bir endianess seçeriz.

Örneğin, böyle bir kod satırımız olduğunu varsayalım

0x1F & 0xEF

Sonucu bir kağıt üzerinde elle nasıl hesaplarsınız?

  MSB   0001 1111  LSB
        1110 1111
result: 0000 1111

Burada hesaplama yapmak için bir Big Endian formatı kullanıyoruz. Aynı sonucu hesaplamak ve elde etmek için Little Endian'ı da kullanabilirsiniz.

Btw, sayıları kod yazdığımızda, sanırım Big Endian formatına benziyor. 123456veya 0x1Fen anlamlı sayılar soldan başlar.

Yine, kağıda bir değerin ikili bir biçimini yazar yazmaz, sanırım zaten bir Endianess seçtik ve değeri bellekten gördüğümüz gibi görüyoruz.

Dolayısıyla soruya geri dönersek, bir vardiya işleminin LSB'den (en az önemli bayt) MSB'ye (en önemli bayt) geçiş<< olduğu düşünülmelidir .

Sonra sorudaki örneğe gelince:

numb=1025

Küçük Endian

LSB 00000001 00000100 00000000 00000000 MSB

Yani << 10olacağını 10bitLSB'den MSB ye kayıyor.


<< 10Little Endian formatı için adım adım karşılaştırma ve işlemler:

MSB                                        LSB
    00000000  00000000  00000100  00000001  numb(1025)
    00000000  00010000  00000100  00000000  << 10

LSB                                        MSB
    00000000  00000100  00010000  00000000 numb(1025) << 10, and put in a Little Endian Format

LSB                                        MSB
    00000001  00000100  00000000  00000000 numb(1205) in Little Endian format
    00000010  00001000  00000000  00000000 << 1 
    00000100  00010000  00000000  00000000 << 2 
    00001000  00100000  00000000  00000000 << 3 
    00010000  01000000  00000000  00000000 << 4
    00100000  10000000  00000000  00000000 << 5
    01000000  00000000  00000001  00000000 << 6
    10000000  00000000  00000010  00000000 << 7
    00000000  00000001  00000100  00000000 << 8
    00000000  00000010  00001000  00000000 << 9
    00000000  00000100  00010000  00000000 << 10 (check this final result!)

Vaov! OP açıklandığı gibi beklenen sonucu elde!

OP'nin beklenen sonucu alamadığı sorunlar:

  1. LSB'den MSB'ye geçmediği anlaşılıyor.

  2. Bitleri Little Endian biçiminde kaydırırken şunu fark etmelisiniz (şükürler olsun ki anlıyorum):

LSB 10000000 00000000 MSB << 1olduğunu
LSB 00000000 00000001 MSB, değil LSB 01000000 00000000 MSB

Çünkü her birey için 8bits, onu bir MSB 00000000 LSBBig Endian formatında yazıyoruz .

Yani böyle

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB


Sonuç olarak:

  1. Bitsel işlemlerin blablablabla'yı soyutladığı söylense de, bitsel işlemleri elle hesapladığımızda, kağıda ikili formatı yazarken hangi endianess'i kullandığımızı bilmemiz gerekir. Ayrıca tüm operatörlerin aynı endianess'i kullandığından emin olmalıyız.

  2. OP beklenen sonucu alamamış olması nedeniyle kaymayı yanlış yapmıştı.

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.