Conteúdos da cadeira

LEGv8: registos e memória

Os 32 registos, endereçamento ao byte, alinhamento, endianness e a pilha.

Markdown

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Envia o link e pede à IA para ler a página. No Gemini, cola a pergunta copiada.

Ver pergunta para copiar
Nesta página

O LEGv8 é o conjunto de instruções usado na cadeira para mostrar como um processador real recebe ordens. É um subconjunto didático do ARMv8, com instruções de 32 bits e registos de 64 bits. Esta página apresenta onde os dados vivem: os registos e a memória.

Os registos

O LEGv8 tem 32 registos de 64 bits, numerados de X0 a X30 mais um registo especial. Três têm papéis fixos que deves saber de cor:

RegistoNomePapel
X28SP (stack pointer)Apontador da pilha, o endereço mais recente da pilha
X29FP (frame pointer)Apontador da moldura do procedimento atual
X30LR (link register)Guarda o endereço de regresso nas chamadas
XZRzero registerRegisto 31: ler dele devolve sempre 0

Os restantes, X0 a X27, são de uso geral: guardam operandos, resultados intermédios e argumentos de procedimentos. Aceder a um registo é muito mais rápido do que aceder à memória, por isso uma boa utilização dos registos evita instruções de LOAD. Constantes escritas diretamente na instrução chamam-se operandos imediatos e também evitam idas à memória.

Memória endereçada ao byte

A memória é endereçada ao byte: cada endereço identifica um byte de 8 bits. Uma instrução de acesso a uma palavra dupla (doubleword, 64 bits) como LDUR X0, [X1, #0] refere-se às posições de memória 5000 a 5007 se X1 valer 5000.

Isto cria uma obrigação: para ler 8 bytes de uma vez, o endereço tem de ser múltiplo de 8. O hardware soma o deslocamento ao registo base e depois aplica um deslocamento lógico à esquerda (LSL) para alinhar o acesso. Na prática, quando escreveres um deslocamento para uma doubleword, pensa em múltiplos de 8.

Endianness

Quando um valor de vários bytes vive em endereços consecutivos, há duas convenções possíveis para a ordem dos bytes:

  • Big-endian: o byte mais significativo fica no menor endereço de memória.
  • Little-endian: o byte menos significativo fica no menor endereço de memória.

O valor 0x12345678 guardado no endereço 1000 em big-endian põe 0x12 em 1000, 0x34 em 1001, 0x56 em 1002 e 0x78 em 1003. Em little-endian, a ordem inverte-se: 0x78 fica em 1000 e 0x12 em 1003. A convenção tem de ser igual nos dois lados de qualquer troca de dados, ou os valores saem trocados.

A pilha

A pilha (stack) é uma zona de memória com disciplina LIFO: o último a entrar é o primeiro a sair (last in, first out). O registo SP aponta sempre para o endereço mais recente da pilha.

Colocar dados na pilha (push) significa subtrair ao SP, porque a pilha cresce para endereços mais baixos. Tirar dados (pop) significa adicionar ao SP. A pilha é necessária nos procedimentos non-leaf, os que invocam outros procedimentos: antes de chamar, o procedimento guarda os seus registos na pilha, e ao regressar repõe-nos.

A memória organiza-se por uso: as variáveis automáticas (locais) vivem na zona da pilha e são descartadas; as variáveis estáticas e globais são preservadas e crescem no sentido contrário à pilha; os vetores, as listas ligadas e outras estruturas dinâmicas vivem na heap.

Ver o ficheiro no GitHub

À tua maneira

Escolhe como preferes ler.

Aparência
Ajustar cores e largura
Cor de destaque do tema FEUP
Tipo de letra

Álgebra, lógica e uma ideia de cada vez.

As tuas escolhas ficam guardadas neste navegador.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.