Dúvida variavel.

Software e Hardware para linha ARM

Moderadores: 51, guest2003, Renie, gpenga

Dúvida variavel.

Mensagempor fabim » 08 Abr 2009 20:06

Procurei e não achei, por isto pergunto.

No arm7 LPC21XX.

Quando é definido.

Byte meu_byte;

Pelo que eu pude observar, em uma rotininha.
O arm trata variaveis, mesmo um byte, como sendo 32 bits.

Se eu vou passar o MEU_BYTE como endereço para um ponteiro.

Sendo que o MEU_BYTE agora é.

Byte Meu_byte[25];

Quer dizer que ele vai ocupar , 4 * 25 posições ?

Nossa alguém pode me explicar isso!?

fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Francesco » 08 Abr 2009 22:30

Normalmente processadores de 32 bits tratam em múltiplos de 32 bits. Isso significa que:

Código: Selecionar todos
Byte meu_byte[ 1 ] ; // Ocupa 4 bytes
Byte meu_byte[ 2 ] ; // Ocupa 4 bytes
Byte meu_byte[ 3 ] ; // Ocupa 4 bytes
Byte meu_byte[ 4 ] ; // Ocupa 4 bytes
Byte meu_byte[ 5 ] ; // Ocupa 8 bytes
Byte meu_byte[ 6 ] ; // Ocupa 8 bytes
Byte meu_byte[ 7 ] ; // Ocupa 8 bytes
Byte meu_byte[ 8 ] ; // Ocupa 8 bytes
Byte meu_byte[ 9 ] ; // Ocupa 12 bytes


Logo...

Código: Selecionar todos
Byte meu_byte[ 25 ] ; // Ocupa 28 bytes


Tente tirar a dúvida usando a rotina sizeof()!
Avatar do usuário
Francesco
Word
 
Mensagens: 699
Registrado em: 04 Mar 2008 00:22
Localização: São Paulo - SP

Mensagempor Monk » 08 Abr 2009 23:51

Isso depende mais do compilador do que da arquitetura, mas seria muita ineficia uma variavel de 1 byte ocupar o espaço de 4 bytes. Não acredito que nenhum compilador faça isso.

Agora ponteiros são endereços de mémoria, e portanto em um processador que usa endereçamento de 32 bits eles ocupam quatro bytes.

Portanto, quando vc declara:

Byte Meu_byte[25];

Voce está declarando 25 bytes de dados, e um ponteiro(que ocupa 4 bytes) que aponta para o primeiro byte dos 25 declarados.

Quer fazer um teste. Declare:

char meu_array[4000]

E vejaê a quantidade ram usada, depois troque por

int meu_array[4000];

Sê a quantidade se mantiver, seu compilador é doidão.
Monk
Bit
 
Mensagens: 32
Registrado em: 26 Set 2007 17:14
Localização: Salvador, BA

Re: Dúvida variavel.

Mensagempor polesapart » 09 Abr 2009 00:20

Como os colegas já colocaram, assumindo que este tipo "Byte" seja um typedef de um char, ele ocupa (ou deveria ocupar) apenas um byte, e os ponteiros tem 4 bytes.

Isto considerando o layout na memória RAM, pois quando o arm vai trabalhar com o dado e o lê para um registrador, ele faz zerando os 24 bits superiores, pois ele não tem registradores de 8 ou 16 bits, ao contrário de algumas arquiteturas (se vc tá acostumado com o assembler do intel x86, lá você tem os al, ax, eax e outros "apelidos" para o mesmo registrador, que expõe apenas os "n" bits inferiores ou superiores do mesmo dado).

O ARM pode acessar bytes em qualquer endereço de memória válido, sem precisar ser alinhado (ao contrário dos dados de 16 e 32 bits), portanto não faria sentido algum que um byte ocupasse mais dados.

Mas se vc fizer isto:

typedef struct {
char Mych;
} Byte;

E depois:

Byte Meu_Byte[1000];

Vai ter um array ocupando 4k e não 1k. É que por padrão as structs e unions são alinhadas em 32 bits, mesmo que os membros ocupem menos que isto, e para que isto ocorra é preciso preencher cada item com espaços "vazios".
Warning: time of day goes back (-163479us), taking countermeasures. :)
Avatar do usuário
polesapart
Byte
 
Mensagens: 477
Registrado em: 19 Nov 2007 12:56
Localização: Curitiba

Mensagempor fabim » 09 Abr 2009 00:25

o compilador em questão é o keil.

Eu acho que tinha achado, mais ele continua dando um de dificil..
Amanhã eu coloco o exemplo do que eu estou tentando fazer, e o keil esta me achando com cara de tonto.

brigadão,


fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor mastk » 09 Abr 2009 11:50

A regra em compiladores de alto nivel, eh um BIT,BYTE,WORD ira ocupar o tamanho do BARRAMENTO de CPU para evitar desperdicio de peformace.
Avatar do usuário
mastk
Dword
 
Mensagens: 4407
Registrado em: 14 Out 2006 20:43

Mensagempor Francesco » 09 Abr 2009 12:11

Uma informação importante para processadores de 32 bits é que não é possível fracionar endereços para uma palavra inteira. Explico, suponha a memória abaixo:

Código: Selecionar todos
         +---+---+---+---+
   2000h |   |   |   |   |
         +---+---+---+---+
   2004h |   |   |   |   |
         +---+---+---+---+
   2008h |   |   |   |   |
         +---+---+---+---+
   200Ch |   |   |   |   |
         +---+---+---+---+
   2010h |   |   |   |   |
         +---+---+---+---+


Quando você aloca as variáveis na seguinte sequência:

Código: Selecionar todos
char var1 ;
short int var2 ;
short int var3 ;
long int var4 ;


O primeiro var1 fica no endereço 2000h, o segundo var2 fica no 2001h e ocupa o 2002h também. No entanto o var3 não fica no 2003h, pois ele não cabe na primeira palavra. Ele vai para 2004h e 2005h.

Var4 também não cabe após var3, então ele é alocado em 2008h.

Por isso é importante se preocupar na hora de alocar a memória. Colocar primeiramente as variáveis de 32 bits, em seguida as de 16 bits e terminar com as de 8 bits.
Avatar do usuário
Francesco
Word
 
Mensagens: 699
Registrado em: 04 Mar 2008 00:22
Localização: São Paulo - SP

Mensagempor chipselect » 09 Abr 2009 12:27

Não existe nenhuma opção de alinhamento de memória nos compiladores para ARM?
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor polesapart » 09 Abr 2009 12:41

Francesco escreveu:Uma informação importante para processadores de 32 bits é que não é possível fracionar endereços para uma palavra inteira. Explico, suponha a memória abaixo:

(cortei)


Isto depende da ABI (application binary interface), que é a especificação definindo como os dados são alocados e acessados, que é sempre baseada no layout de memória do processador em questão. Alguns processadores de 32 bits só acessam o barramento em 32 bits e só fazem leituras/gravações alinhadas em múltiplos de 32 bits. Neste caso quando é feita a leitura/gravação de dados, há sempre necessidade de mascarar e/ou escorregar dados no processo. Não é exatamente o caso do ARM, pois a micro-arquitetura do lado do processador permite acessar dados com alinhamento natural em 32, 16 e 8 bits, e, mais recentemente (nos cortex-m3 por exemplo), incorporou suporte opcional (configurável em tempo de execução) para leituras totalmente desalinhadas, mantendo os mesmos tamanhos.

É importante ressaltar que embora o barramento suporte isto, as vezes a memória/porta do outro lado do dispositivo não suporta esta seleção de tamanho da i/o, e naquela área é necessário fazer os acessos (especialmente as gravações) conforme suportado. É o caso de alguns periféricos dos LPC 2xxx da NXP, no manual de alguns modelos é pedido que o acesso a alguns registradores seja sempre feito em 32 bits para evitar corromper os bits adjacentes, pois o circuito que trata o acesso para aquela mascara de endereços não possui a lógica adequada para fazer o read-modify-write do tamanho correto sozinha.

Mas voltando a ABI, a maioria dos compiladores modernos para ARM trabalham com a ARM EABI, que é especificada pela própria ARM, de modo a aumentar a interoperabilidade entre código gerado por vários compiladores. Eu desconheço os detalhes internos da EABI, pois trabalho com uma especificação anterior (apcs-gnu se não me engano), e nela, o que ocorre é que a geração de código para acesso a variáveis globais geralmente assume que o linker poderá gerar um layout de memória bastante diferente. Uma coisa que ele pode fazer, por exemplo, é ordenar os símbolos não inicializados conforme o tamanho do alinhamento, do maior para o menor, de modo que os dados que ocupem um byte isoladamente acabam sendo alocados no final da área, independente da ordem de declaração (opção --sort-common). Isto é feito para evitar justamente gaps (áreas sem uso) na memória quando as declarações são feitas inter-mixando dados de tamanho variável, como no teu exemplo.

Não tendo esta opção, prevalece o teu conselho:

Francesco escreveu:Por isso é importante se preocupar na hora de alocar a memória. Colocar primeiramente as variáveis de 32 bits, em seguida as de 16 bits e terminar com as de 8 bits.
Warning: time of day goes back (-163479us), taking countermeasures. :)
Avatar do usuário
polesapart
Byte
 
Mensagens: 477
Registrado em: 19 Nov 2007 12:56
Localização: Curitiba

Mensagempor mastk » 09 Abr 2009 12:52

Uma informação importante para processadores de 32 bits é que não é possível fracionar endereços para uma palavra inteira. Explico, suponha a memória abaixo:

Code:

+---+---+---+---+
2000h | | | | |
+---+---+---+---+
2004h | | | | |
+---+---+---+---+
2008h | | | | |
+---+---+---+---+
200Ch | | | | |
+---+---+---+---+
2010h | | | | |
+---+---+---+---+


Quando você aloca as variáveis na seguinte sequência:

Code:

char var1 ;
short int var2 ;
short int var3 ;
long int var4 ;


O primeiro var1 fica no endereço 2000h, o segundo var2 fica no 2001h e ocupa o 2002h também. No entanto o var3 não fica no 2003h, pois ele não cabe na primeira palavra. Ele vai para 2004h e 2005h.

Var4 também não cabe após var3, então ele é alocado em 2008h.

Por isso é importante se preocupar na hora de alocar a memória. Colocar primeiramente as variáveis de 32 bits, em seguida as de 16 bits e terminar com as de 8 bits.


Errado, pelo menos nas placa que fiz de LPC23... qlqr coisa, e no 68K, quando se utiliza um BUS maior que 8 bits, as linhas de endereco baixas deixam de ser utilizadas
Avatar do usuário
mastk
Dword
 
Mensagens: 4407
Registrado em: 14 Out 2006 20:43

Mensagempor polesapart » 09 Abr 2009 12:52

chipselect escreveu:Não existe nenhuma opção de alinhamento de memória nos compiladores para ARM?


Existe. No que eu trabalho (gcc com alvo gnu-elf) por padrão é usado o mais eficiente, ou seja, quando o alinhamento é desnecessário, ele não é forçado. Mas há como obrigá-lo a gerar código para acessar variáveis fora de alinhamento, inclusive dá pra por um atributo (equivalente ao pragma de outros compiladores) apenas nas variáveis ou tipos de dados (com typedef) que você quer que ele não alinhe de jeito nenhum.

Aí todo acesso é emulado, por exemplo, compare o código pra retornar uma int alinhada:

Código: Selecionar todos
unsigned int get_int(const unsigned int *ptr)
{
  return *ptr;
}


E o assembly gerado:

Código: Selecionar todos
ldr     r0, [r0, #0]
bx      lr



Com aquele pra acessar uma int independente do alinhamento:
Código: Selecionar todos

typedef struct __attribute__((packed))
{
  unsigned int value;
} pqp;

unsigned int get_int(const pqp *ptr)
{
  return ptr->value;
}


E o respectivo assembly:

Código: Selecionar todos
ldrb    r3, [r0, #0]
ldrb    r2, [r0, #1]
ldrb    r1, [r0, #2]
orr     r3, r3, r2, asl #8
ldrb    r0, [r0, #3]
orr     r3, r3, r1, asl #16
orr     r0, r3, r0, asl #24
bx      lr
Warning: time of day goes back (-163479us), taking countermeasures. :)
Avatar do usuário
polesapart
Byte
 
Mensagens: 477
Registrado em: 19 Nov 2007 12:56
Localização: Curitiba

Mensagempor fabim » 09 Abr 2009 23:41

ai ai, deu um nó no meu cérebro.
Bom eu peguei a idéia sim!!
Acerca da memória.

O rodrigo, me deu um help, e consegui passar pelo ponto que estava travando.

Mais gostei destas informações, muito interessantes, e antes desconhecidas por mim.

Existe mais alguma coisa, que um starter arm deveria saber ?

fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?


Voltar para ARM

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x