Moderators Leandro Fróes Posted January 3, 2018 at 03:59 AM Moderators Share Posted January 3, 2018 at 03:59 AM Boa noite!! Hoje estava lendo um dos artigos da coluna "Fundamentos da Computação Ofensiva" na revista da h2hc e me deparei com um trecho de código bem bacana, ele é bem simples e explica bastante coisa. Minha intenção aqui não é explicar ordenação de bytes, acho que o artigo explicou muito bem isso, vou apenas falar de uma única linha de código (de acordo com o meu entendimento) e como ela pode ser útil. O código é esse aqui: #include <stdio.h> int main(){ int x = 1; if(*(char *)&x == 1) printf("Little Endian!!\n"); else printf("Big endian!!"); return 0; } user@test:/home/codes# ./teste Little Endian!! A ideia é testar o endianness (ordenação) dos bytes. O que está rolando no código acima? Assumindo um inteiro de 32 bits atribuimos o valor 1 à ele. Dentro do condicional IF acontece a seguinte mágica: converte o endereço de x (que é de um inteiro) para o endereço de um char e o operador * que precede o casting (char*) diz que estamos apontando para o conteúdo daquele endereço e SE o valor que estamos apontando for 1, é Little Endian. Pera, que? Blz, para entender a linguagem decidi fazer um código bem newbie pra mostrar números e ver o que está acontecendo no código acima: #include <stdio.h> int main(){ int x = 1; printf("Valor de x: %d\n", x); int y = *(char *)&x; printf("Valor de y: %d\n", y); char *p = (char *)&x; printf("Valor apontado por p: %d\n", *p); return 0; } user@test:/home/codes# ./teste Valor de x: 1 Valor de y: 1 Valor apontado por p: 1 O que podemos notar aqui (assumindo de fato que é little endian) é que na declaração do ponteiro para char p que toda essa mágica é meramente um casting no endereço da variável. Note que em y fiz toda a linha do código e o valor deu realmente 1, mas em p tirei o primeiro * e mantive apenas o casting de fato, com isso imprimi o valor apontado pelo ponteiro p que recebeu o endereço com o casting e deu 1 também!! Ok, mas até agora não entendi o endianness. A sacada é que se for Little Endian os bits no endereço de x estariam dessa forma: 00000000 00000000 00000000 00000001, com o casting do endereço para um tipo char nós limitamos o teste para apenas a célula da direta e SE esta célula de oito bits possuir o valor 1 (que é o caso) será little endian, pois neste os bytes menos significativos são codificados primeiro. Caso neste teste o valor seja diferente de 1 (no caso zero) é porque é Big Endian pois neste os bytes mais significativos (da esquerda) são codificados primeiro. Esse assunto deve ser bem simples pra maioria de vocês, mas eu curto ler sobre coisas simples e ver o quão essenciais são, espero não ter sido confuso e me corrijam qualquer besteira que escrevi. Caso tenha uma visão diferente por favor, me dê um toque, gostaria de saber mais sobre. Abs!! Link to comment Share on other sites More sharing options...
gzn Posted January 18, 2018 at 02:50 PM Share Posted January 18, 2018 at 02:50 PM Interessante. A convenção little começa pelo menos significativo (começa pelo menor, little) e o outro pelo mais significativo (começa pelo maior, big). Do menor endereço até o maior. E como os dados ficam nos registradores? Veja uma explicação na internet: Citar The only time endianness matters is when you look at the value as bytes, not as dwords. 0FFEEDDCCh is always going to load as 0FFEEDDCCh, but they are stored in memory differently. Consider this data in memory: 00004000: 00 11 22 33 44 55 66 77 On a little-endian processor, if you load that into a 32-bit register, you get this: mov eax, [4000h] ; 0x33221100 But if I do the same operation on a big-endian processor: ldr r3, #0x4000 ; 0x00112233 With that same piece of memory, notice the differences: Little Big Load byte 00 00 Load word 1100 0011 Load dword 33221100 00112233 -- Tim Roberts, ti...@probo.com Providenza & Boekelheide, Inc. Se alguém quiser comentar mais alguma coisa para esclarecer mais o assunto será bem vindo. Link to comment Share on other sites More sharing options...
fredericopissarra Posted January 18, 2018 at 09:24 PM Share Posted January 18, 2018 at 09:24 PM No GCC, se quiser testar pelo "endianess" para garantir que seu código funcionará corretamente (se tentar obter frações de dados maiores), pode usar: #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ... #else ... #endif Essas são umas das muitas definições padrão do GCC, que podem ser vistas com: $ gcc -dM -E - < /dev/null | less []s Fred Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.