Qual é a vantagem do formato little endian?

118

Os processadores Intel (e talvez alguns outros) usam o formato little endian para armazenamento.

Eu sempre me pergunto por que alguém iria querer armazenar os bytes na ordem inversa. Este formato tem alguma vantagem sobre o formato big endian?

    
por Cracker 24.07.2011 / 21:04
fonte

10 respostas

180

Existem argumentos de qualquer forma, mas um ponto é que em um sistema little-endian, o endereço de um determinado valor na memória, tomado como 32, 16 ou 8 bits de largura, é o mesmo.

Em outras palavras, se você tiver na memória um valor de dois bytes:

0x00f0   16
0x00f1    0

considerando que '16' como um valor de 16 bits (c 'curto' na maioria dos sistemas de 32 bits) ou como um valor de 8 bits (geralmente c 'char') altera somente a instrução de busca que você usa - não o endereço que você busca.

Em um sistema big-endian, com o exposto acima:

0x00f0    0
0x00f1   16

você precisaria incrementar o ponteiro e depois executar a operação de busca mais restrita no novo valor.

Então, em suma, "nos sistemas little endian, os elencos não funcionam".

    
por 24.07.2011 / 22:04
fonte
38

I always wonder why someone would want to store the bytes in reverse order.

Big-endian e little-endian são apenas "ordem normal" e "ordem reversa" de uma perspectiva humana, e somente se todos estes forem verdadeiros ...

  1. Você está lendo os valores na tela ou no papel.
  2. Você coloca os endereços de memória inferiores à esquerda e os maiores à direita.
  3. Você está escrevendo em hexadecimal, com o nybble de alta ordem à esquerda ou binário, com o bit mais significativo à esquerda.
  4. Você leu da esquerda para a direita.

Essas são todas convenções humanas que não importam a CPU. Se você fosse manter # 1 e # 2 e virar # 3, little-endian pareceria "perfeitamente natural" para pessoas que lêem árabe ou hebraico, que são escritos da direita para a esquerda.

E existem outras convenções humanas que tornam o big-endian que não parecem naturais, como ...

  • O byte "superior" (mais significativo) deve estar no endereço de memória "superior".

De volta, quando eu estava programando principalmente o 68K e o PowerPC, eu considerava o big-endian "certo" e o little-endian como "errado". Mas desde que eu tenho trabalhado mais ARM e Intel, eu me acostumei a little-endian. Realmente não importa.

    
por 24.07.2011 / 23:14
fonte
33

OK, aqui está o motivo pelo qual eu tive isso explicado para mim: Adição e subtração

Quando você adiciona ou subtrai números de múltiplos bytes, precisa começar com o byte menos significativo. Se você está adicionando dois números de 16 bits, por exemplo, pode haver um carry do byte menos significativo para o byte mais significativo, então você precisa começar com o byte menos significativo para ver se existe um carry. Essa é a mesma razão pela qual você começa com o dígito mais à direita ao fazer a adição à mão. Você não pode começar pela esquerda.

Considere um sistema de 8 bits que busca bytes sequencialmente da memória. Se ele pega o byte menos significativo primeiro , ele pode começar a fazer a adição enquanto o byte mais significativo está sendo buscado da memória. Este paralelismo é porque o desempenho é melhor em little endian em tal sistema. Se tivesse que esperar até que os dois bytes fossem buscados da memória ou buscá-los na ordem inversa, levaria mais tempo.

Isso está em sistemas antigos de 8 bits. Em um CPU moderno eu duvido que a ordem de byte faça alguma diferença e nós usamos little endian apenas por razões históricas.

    
por 25.07.2011 / 22:15
fonte
13

Com processadores de 8 bits, certamente foi mais eficiente, você pode executar uma operação de 8 ou 16 bits sem precisar de código diferente e sem precisar armazenar valores extras.

Ainda é melhor para algumas operações de adição se você estiver lidando com um byte de cada vez.

Mas não há razão para que big-endian seja mais natural - em inglês você usa treze (little endian) e vinte e três (big endian)

    
por 24.07.2011 / 21:15
fonte
7

A convenção japonesa data é "big endian" - aaaa / mm / dd. Isso é útil para ordenar algoritmos, que podem usar uma simples comparação de strings com a regra usual de primeiro caractere que é a mais significativa.

Algo semelhante se aplica a números big-endian armazenados em um registro de campo mais significativo primeiro. A ordem de importância dos bytes dentro dos campos corresponde à significância dos campos dentro do registro, portanto, você pode usar um memcmp para comparar registros, não se importando muito em comparar duas palavras longas, quatro palavras ou oito bytes separados.

Inverta a ordem de significância dos campos e você terá a mesma vantagem, mas para números little-endian em vez de big-endian.

Isso tem muito pouco significado prático, é claro. Se sua plataforma é big-endian ou little-endian, você pode solicitar um campo de registros para explorar esse truque se realmente precisar. É só uma dor se você precisar escrever código portátil .

Eu também posso incluir um link para o apelo clássico ...

link

EDITAR

Um pensamento extra. Certa vez, escrevi uma grande biblioteca de inteiros (para ver se podia) e, para isso, os trechos de 32 bits são armazenados na ordem little-endian, independentemente de como a plataforma ordena os bits nesses blocos. As razões foram ...

  1. Muitos algoritmos começam naturalmente a trabalhar no final menos significativo e querem que esses fins sejam correspondidos. Por exemplo, além disso, os carregamentos se propagam para dígitos cada vez mais significativos, por isso faz sentido começar pelo menos significativo.

  2. Aumentar ou diminuir um valor significa apenas adicionar / remover partes no final - não é necessário alterar os pedaços para cima / baixo. A cópia ainda pode ser necessária devido à realocação de memória, mas não com frequência.

Isso não tem nenhuma relevância óbvia para processadores, é claro - até que as CPUs sejam feitas com suporte a números inteiros de hardware, é puramente uma coisa de biblioteca.

    
por 24.07.2011 / 22:42
fonte
6

Ninguém mais respondeu POR QUE isso pode ser feito, muitas coisas sobre as conseqüências.

Considere um processador de 8 bits que pode carregar um único byte da memória em um determinado ciclo de clock.

Agora, se você quiser carregar um valor de 16 bits, digamos, no único registrador de 16 bits que você possui - isto é, o contador de programa, então uma maneira simples de fazê-lo é:

  • Carregar um byte do local de busca
  • desloca esse byte para a esquerda 8 lugares
  • incrementa o local de busca de memória em 1
  • carrega o próximo byte (na parte de baixa ordem do registro)

o resultado: você só incrementa o local de busca, você só carrega na parte baixa de seu registro mais amplo, e você só precisa mudar para a esquerda. (Claro que deslocar para a direita é útil para outras operações, por isso este é um pouco espectacular).

Uma conseqüência disso é que o material de 16 bits (byte duplo) é armazenado na ordem Most..Least. Ou seja, o endereço menor tem o byte mais significativo - o big endian.

Se você, ao invés disso, tentasse carregar usando little endian, você precisaria carregar um byte na parte inferior de seu registro grande, depois carregar o próximo byte em uma área de preparação, deslocá-lo e, em seguida, colocá-lo no topo de seu registro mais amplo. Ou use um arranjo mais complexo de gating para poder carregar seletivamente no byte superior ou inferior.

O resultado de tentar usar o little endian é que você precisa de mais silício (switches e portões) ou mais operações.

Em outras palavras, em termos de obtenção de retorno para o dinheirinho nos velhos tempos, você tem mais impacto na maioria das performances e na menor área de silício.

Hoje em dia, essas considerações e praticamente irrelevantes, mas coisas como preenchimento de pipeline podem ainda ser um grande negócio.

Quando se trata de escrever s / w, a vida é freqüentemente mais fácil quando se usa um endereçamento little endian.

(E os processadores big endian tendem a ser big endian em termos de ordenação de byte e little endian em termos de bits-em-bytes. Mas alguns processadores são estranhos e usarão big endian bit ordering e byte ordering). torna a vida muito interessante para o designer h / w que adiciona periféricos mapeados na memória, mas não tem outra conseqüência para o programador.

    
por 25.07.2011 / 06:44
fonte
3

jimwise fez um bom ponto. Existe outro problema, em little endian você pode fazer o seguinte:

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

Mais direto para programadores que não são afetados pela desvantagem óbvia de locais trocados na memória. Eu pessoalmente acho que o big endian é inverso do que é natural :). 12 devem ser armazenados e escritos como 21:)

    
por 24.07.2011 / 23:06
fonte
1

I always wonder why someone would want to store the bytes in reverse order

O número decimal é escrito em big endian. É também como você escreve em inglês. Você começa com o dígito mais significativo e o segundo mais significativo para o menos significativo. por exemplo,

1234

são mil duzentos e trinta e quatro.

É assim que o big endian é às vezes chamado de ordem natural.

Em little endian, esse número seria um, vinte, trezentos e quatro mil.

No entanto, quando você realiza aritmética como adição ou subtração, começa com o fim.

  1234
+ 0567
  ====

Você começa com 4 e 7, escreve o dígito mais baixo e lembra o carry. Então você adiciona 3 e 6 etc. Para adicionar, subtrair ou comparar, é mais simples implementar, se você já tiver lógica para ler a memória em ordem, se os números estiverem invertidos.

Para suportar big endian desta forma, você precisa de lógica para ler a memória ao contrário, ou você tem um processo RISC que só opera em registradores. ;)

Grande parte do design do Intel x86 / Amd x64 é histórico.

    
por 26.07.2011 / 08:49
fonte
0

Big-endian é útil para algumas operações (comparações de "bignums" de molas de comprimento de octetos iguais à mente). Little-endian para os outros (adicionando dois "bignums", possivelmente). No final, isso depende do que o hardware da CPU foi configurado, geralmente é um ou outro (alguns chips MIPS foram, IIRC, comutáveis na inicialização para serem LE ou BE).

    
por 25.07.2011 / 17:34
fonte
0

Quando somente o armazenamento e a transferência com comprimentos variáveis estão envolvidos, mas não há aritmética com múltiplos valores, então o LE é geralmente mais fácil de escrever, enquanto o BE é mais fácil de ler.

Vamos fazer uma conversão de int-string (e de volta) como um exemplo específico.

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

Quando o int é convertido para a string, o dígito menos significativo é mais fácil de extrair do que o dígito mais significativo. Tudo pode ser feito em um loop simples com uma condição final simples.

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] = '
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');
}
'; // val_str is now in LE "148" // i is the length of the result without termination, can be used to reverse it

Agora tente o mesmo na ordem de BE. Normalmente, você precisa de outro divisor que contenha a maior potência de 10 para o número específico (aqui, 100). Você primeiro precisa encontrar isso, é claro. Muito mais coisas para fazer.

A string para conversão int é mais fácil de fazer em BE, quando é feita como a operação de gravação reversa. Escreva as lojas com o dígito mais significativo por último, por isso deve ser lido primeiro.

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

Agora faça o mesmo na ordem LE. Novamente, você precisaria de um fator adicional começando com 1 e sendo multiplicado por 10 para cada dígito.

Assim, eu geralmente prefiro usar BE para armazenamento, porque um valor é escrito exatamente uma vez, mas lido pelo menos uma vez e talvez muitas vezes. Por sua estrutura mais simples, normalmente também faço o caminho para converter em LE e, em seguida, inverter o resultado, mesmo que ele escreva o valor uma segunda vez.

Outro exemplo para o armazenamento BE seria a codificação UTF-8 e muito mais.

    
por 12.11.2012 / 12:30
fonte