RISC-V: computador, registos e memória
RV32, endereços de bytes, little endian, organização do programa e diretivas do RARS.
O CPU lê a instrução no endereço indicado pelo PC, identifica a operação e os operandos, executa-a e escolhe o endereço seguinte. Esta sequência é fetch, decode e execute; o PC é um registo que permite localizar a instrução e não contém o seu código.
Programa e arquitetura
A ISA, arquitetura do conjunto de instruções, define as instruções e os efeitos observáveis pelo programa. A organização interna do CPU pode mudar sem mudar esses efeitos. A ABI, interface binária de aplicação, acrescenta acordos entre programas, como os registos de argumentos e a utilização da pilha.
Um compilador traduz código de alto nível; um assembler converte assembly em código máquina. O linker resolve ligações entre módulos e símbolos. O loader coloca o programa em memória e prepara a execução. Uma etiqueta não é um registo: é um nome que o assembler associa a uma posição.
RISC-V usa uma organização load/store: a aritmética opera sobre registos, enquanto loads e stores transferem entre registos e memória. Uma instrução como add não soma diretamente duas posições de memória; RISC favorece operações simples e regulares, e CISC inclui operações mais complexas. Esta distinção não decide, por si só, qual computador executa um programa mais depressa.
Registos de RV32
RV32I tem 32 registos inteiros, x0 a x31, de 32 bits. x0, também chamado zero, lê sempre 0, e uma tentativa de escrever nele descarta o resultado; o PC é separado destes registos.
Os nomes t0, a0 ou sp são aliases, não registos adicionais. Alguns são:
| Registo | Alias | Uso habitual |
|---|---|---|
| x1 | ra | Endereço de retorno |
| x2 | sp | Topo da pilha |
| x5, x6, x7 | t0, t1, t2 | Temporários |
| x8, x9 | s0, s1 | Valores preservados por uma rotina |
| x10 a x17 | a0 a a7 | Argumentos e temporários |
| x18 a x27 | s2 a s11 | Valores preservados |
| x28 a x31 | t3 a t6 | Temporários |
Um registo guarda bits. Uma instrução pode tratá-los como número com sinal, sem sinal, máscara ou endereço. A instrução de comparação é que escolhe a interpretação.
Endereços e little endian
A memória é endereçada ao byte. Uma word tem 4 bytes, uma halfword 2 e um byte 1; com 32 bits de endereço há endereços possíveis, 4 GiB de espaço de endereçamento, o que não obriga um simulador ou computador a ter toda essa RAM.
No ambiente RARS usado aqui, a memória é little endian: o byte menos significativo fica no menor endereço. A ISA RISC-V é invariante no endereço do byte, enquanto o EEI define a ordem dos bytes, por isso não assumes little endian em qualquer sistema RISC-V. Guardar 0x12345678 a partir de 0x1000 dá:
| Endereço | Byte |
|---|---|
| 0x1000 | 78 |
| 0x1001 | 56 |
| 0x1002 | 34 |
| 0x1003 | 12 |
A ordem dos bits dentro do registo não se inverte. Um lw a partir de 0x1000 reconstrói a mesma palavra e um sb altera só um byte; acesso naturalmente alinhado significa endereço múltiplo de 4 para words e de 2 para halfwords. Usa estes alinhamentos nos programas, pois o tratamento de acessos desalinhados depende do ambiente.
Num vetor de words com base B, v[i] fica em . Retomamos os valores 7,-3,10,0, agora guardados com .word em 0x10010000. Cada índice avança 4 bytes a partir da base:
| Índice | Deslocamento em bytes | Endereço | Valor |
|---|---|---|---|
| 0 | 0 | 0x10010000 | 7 |
| 1 | 4 | 0x10010004 | -3 |
| 2 | 8 | 0x10010008 | 10 |
| 3 | 12 | 0x1001000C | 0 |
lw t2,8(t1) com t1=B lê o terceiro elemento, 10. A ISA define endereçamento ao byte, enquanto o RARS escolhe esta base para .data e fornece os serviços ecall; confundir o índice 3 com um deslocamento de 3 bytes seleciona outro endereço e pode desalinhá-lo.
Secções e diretivas
.text contém instruções; .data contém dados estáticos. A pilha guarda informação de chamadas e valores locais; o heap serve para alocações dinâmicas. A memória não ganha tipos por estar numa secção: os programas têm de usar as instruções e tamanhos corretos.
| Diretiva RARS | Efeito |
|---|---|
.word | Emite palavras de 32 bits |
.half, .byte | Emitem unidades de 16 ou 8 bits |
.asciz | Emite texto e byte zero final |
.space n | Reserva n bytes |
.align n | Alinha na fronteira de bytes |
Assim .align 2 alinha words, não em fronteiras de 2 bytes. Uma diretiva orienta o assembler e não é executada pelo CPU; la t0, vetor obtém o endereço, enquanto lw t1,0(t0) lê o conteúdo. Copiar o endereço não copia o elemento.
.data
bytes: .byte 0x80, 0x7f
.align 2
words: .word 0x12345678
.text
.globl main
main:
la t0, bytes
lb a0, 0(t0)
li a7, 1
ecall
li a0, 10
li a7, 11
ecall
lbu a0, 0(t0)
li a7, 1
ecall
li a0, 10
li a7, 11
ecall
la t1, words
lbu a0, 0(t1)
li a7, 1
ecall
li a0, 10
li a7, 11
ecall
sb zero, 1(t1)
lw a0, 0(t1)
li a7, 1
ecall
li a7, 10
ecallExecuta o código para ver a saída e os gráficos.
main é a etiqueta de entrada destes programas. Os serviços ecall pertencem ao RARS: a7 escolhe o serviço e a0 leva o valor. O serviço 1 imprime um inteiro, o 11 imprime um carácter e o 10 termina. No exemplo, lb estende o sinal de 0x80 e lbu acrescenta zeros: o mesmo byte produz valores diferentes conforme a instrução.
Para uma introdução em vídeo a assembly RISC-V, podes consultar Rodrigo Dias:
Exercícios
Store parcial em little endian
Uma word 0xA1B2C3D4 está no endereço alinhado B. Um sb escreve 0x55 em B+2. Qual a word lida depois em B? Mostra os bytes.
Pista
O byte menos significativo fica em B.
Mais uma pista
B+2 corresponde ao terceiro byte na memória, não ao segundo algarismo hexadecimal.
Solução
Antes: D4,C3,B2,A1 nos endereços B..B+3. Depois: D4,C3,55,A1. O lw reconstrói 0xA155C3D4. Só o byte B+2 muda; os outros mantêm-se.
Confere a tua resposta:
- Bytes finais D4,C3,55,A1.
- Word final A155C3D4.
Erros frequentes
Não invertas os algarismos dentro de cada byte.
Índice ou deslocamento?
Um vetor de halfwords começa em 0x10010000. Qual é o endereço do elemento de índice 5? Que alinhamento exige?
Pista
Cada elemento tem 2 bytes.
Solução
O endereço é . É múltiplo de 2, o alinhamento natural da halfword. Não precisa de ser múltiplo de 4 para um acesso lh ou lhu, embora o vetor possa ter uma base alinhada a 4.
Confere a tua resposta:
- Endereço 1001000A.
- Halfword exige múltiplo de 2.
Erros frequentes
Não uses a fórmula B+4i para todos os vetores, porque o deslocamento é o índice vezes o tamanho do elemento.
Diretivas e endereço de etiqueta
A secção começa em B=0x10010000. Emitimos .byte 1,2,3, depois .align 2, depois v: .word 9,10. Qual é o endereço de v e quantos bytes de words foram emitidos?
Pista
O alinhamento insere padding até múltiplo de quatro, ou seja, .align 2 conta potências de 2, não bytes.
Mais uma pista
Depois de três bytes, o próximo endereço é B+3.
Solução
O assembler insere um byte de padding para chegar a B+4. Assim v=0x10010004. As duas words ocupam 8 bytes. As diretivas não são instruções executadas; la obteria este endereço, enquanto lw leria uma dessas words.
Confere a tua resposta:
- v em 10010004, um byte de padding.
- Duas words ocupam oito bytes.
Erros frequentes
.align 2 significa 2² bytes, não duas posições de dados.
