Apresentação da infraestrutura ARM para MC404 Divino César S. Lucas 12 de abril de 2013 1 Conectando na infraestrutura ARM do IC via ssh Este documento descreve como se conectar a uma das três máquinas ARM do laboratório do IC-3. Para ter acesso à infraestrutura, você deve estar em um dos computadores do IC-3 ou, se estiver em casa, conectar-se ao IC-3 via SSH. Exemplo: eu@meupc$ ssh ssh.students.ic.unicamp.br -l ra99999 Uma vez em um computador do IC-3, você pode acessar um computador ARM via SSH usando um dos três endereços abaixo. Note que os dados de login são os mesmos que você utilizou para se logar nos computadores do IC-3. arm1.lab.ic.unicamp.br arm2.lab.ic.unicamp.br arm3.lab.ic.unicamp.br Exemplo: -bash-4.2$ ssh arm1.lab.ic.unicamp.br -l ra99999 Observação: Como você estará se conectando em uma máquina do mesmo domínio (lab.ic.unicamp.br), você pode omitir o domínio quando estiver se conectando. Então, ssh arm1 basta. Uma vez conectado a uma máquina ARM, você contará com uma pasta home particular sua para armazenar seus arquivos, mas que não é o mesmo home do seu Linux do IC-3. Para acessar o seu home ARM a partir de um computador normal do IC-3, acesse a pasta ~mc404/homes/ra99999. Trabalhando remotamente Para testar seus projetos na máquina ARM, você precisará trabalhar via SSH sem acesso físico à máquina1 . Portanto será importante que você se acostume a trabalhar usando apenas o console e editores de texto que não usam interface gráfica (vi, vim, emacs, nano, etc). Vale lembrar alguns truques que facilitam a vida: • Caso esteja editando um arquivo ou executando um programa no console e deseja interrompêlo temporariamente, digamos, para compilar o programa, você pode usar a tecla Ctrl+Z. Isto irá suspender o processo do editor (ou o programa que você estiver executando) e você voltará à linha de comando, livre para rodar outros programas. Para voltar ao programa suspenso, digite na linha de comando fg 1. Se você tem vários programas suspensos, pode precisar outros números além de 1. 1 Se você tem curiosidade pra saber como é a máquina ARM fisicamente, google imx53 e vá em imagens. 1 • Uma conexão por SSH pode cair devido a diversos motivos e problemas de rede, principalmente se você estiver em sua casa. Se isso ocorrer, todos os programas (possivelmente editores de texto trabalhando no projeto) serão fechados automaticamente. Para evitar que você perca a sua sessão devido a uma desconexão, utilize o programa screen. Ao digitar screen no console, você irá abrir um outro shell. Este shell é seguro e, caso você seja desconectado, você pode reconectar e voltar à sua sessão digitando apenas screen -r. Dentro do screen você pode ainda, administrar várias janelas diferentes de terminais. Consule a ajuda do programa digitando ’Ctrl+A’ seguido por ’ ?’ (todos os comandos do screen começam com ’Ctrl+A’). • Se você quer evitar ao máximo usar o terminal, você pode editar os arquivos fonte de seu projeto do computador do IC-3 e salvá-los na pasta ~mc404/homes/ra99999 (seu RA), que é o seu home quando você loga via SSH na máquina ARM. • Finalmente, você pode ainda utilizar o comando scp para enviar arquivos entre duas maquinas. Para enviar o arquivo teste.as da sua maquina local para seu diretorio home do IC-3, voce pode utilizar o seguinte comando: scp teste.as [email protected]:/~ onde ra999999 deve ser substituido pelo seu RA. De forma similar para baixar um arquivo teste2.as do seu diretorio home do IC-3 para a maquina local voce pode digitar o este comando: scp [email protected]:~/teste.as . . 2 Exemplo de código em linguagem assembly ARM O exemplo de código na Listagem 1 mostra um program em linguagem assembly do ARM que utiliza as funções printf e scanf da biblioteca padrão C (libc) para pedir ao usuário que informe um valor inteiro e escrever de volta o valor lido na tela do usuário. Listing 1: Exemplo de código em linguagem ARM assembly 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 .globl main .extern scanf .extern printf .data printf1: printf2: scanf1: numero: .asciz "Digite um numero: " .asciz "Valor lido: %d\n" .asciz "%d" .word 0 .text .align 4 main: push {ip, lr} ldr r0, =printf1 bl printf ldr r1, =numero ldr r0, =scanf1 bl scanf ldr r0, =printf2 ldr r1, =numero ldr r1, [r1] bl printf mov r0, #0 pop {ip, pc} 2 As três primeiras linhas deste arquivo dizem ao montador para considerar que a função main (que será definida logo mais neste arquivo) tem visibilidade global, ou seja funções definidas em outros arquivos podem chamar a função main. Além disso estas linhas também avisam ao montador o interesse de utilizar as funções scanf e printf que foram definidas em outro arquivo (no caso dentro da biblioteca padrão do C). A linha 5, diretiva .data, diz ao montador que a partir desse ponto segue uma serie de definições em relação a alocação de dados. Ou seja, definição de variáveis. As linhas 6, 7 e 8 criam três variáveis (rótulos) com os nomes printf1, printf2 e scanf1 que conterão sequencias de bytes no padrão asci. Estas variáveis são inicializadas com os valores "Digite um numero: ", "Valor lido: %d n"e "%d", respectivamente. Note que como declaramos o tipo das variáveis como .asciz o montador já colocará automaticamente o terminador de cadeia de caracteres ’\0’ no final do conteúdo da variável. Estas variáveis, como você já deve ter imaginado, armazenam a string de formatação que serão utilizadas pelas funções printf e scanf no exemplo. A linha 9 cria uma variável chamada "numero"com o tamanho de uma palavra (.word == 4 bytes) e inicializa o conteúdo para o valor zero. Esta variável guardará o valor que o usuário informar para o programa. A diretiva de montagem da linha 11, .text, diz ao montador que a partir desse ponto segue as definições das instruções (funções) que o programa poderá executar. A linha 12 diz ao montador para alinhar a emissão do mapa de memória do código gerado, em 4 bytes. A linha 14 define um rótulo chamado "main". Em geral linguagens de montagem representam funções utilizando rótulos, ou seja, dando nome para trechos de código. Em seguida quando for necessário fazer a invocação de uma função o programador utiliza uma instrução para fazer um salto para o endereço daquele rótulo. Portanto, nesta linha inicia-se a definição da função "main". A linha 15 é o que chamamos de prólogo da função e basicamente ela serve para garantir que o código que invocou a função atual (função atual seria a main) possa continuar a execução a partir do ponto onde ele parou. Não se preocupe com esse ponto por agora, isso será melhor esclarecido posteriormente. Para fazer a invocação de funções em linguagem de montagem você deve, em geral, fazer um desvio para o rótulo definido como o nome da função. Se a função sendo chamada recebe algum parâmetro os valores deverão ser passados utilizando registradores. Por exemplo, a linha 17 coloca o endereço do rótulo printf1 dentro do registrador r0 e em seguida invoca a execução da função printf. Nesse ponto o programa irá imprimir a mensagem "Digite um numero: "na tela do usuário e voltar a executar o programa (função main) a partir da linha 20. Na linha 20 começamos a fazer a invocação da função scanf. A função scanf recebe, neste caso, dois parâmetros. O primeiro deles, que deve ser armazenado no registrador r0, é a string de formatação utilizada ("%d") e o segundo parâmetro é o endereco de memória onde deve ser armazenado o valor lido, que deve ser armazenado em r1 (=numero). A linha 22 invoca a execução da função scanf. Após o usuário informar o valor o programa continuará a execução a partir da linha 24. Na linha 24 começamos a preparar a invocação da função printf para informar ao usuário o valor que acabamos de ler. Novamente os parâmetros para a função devem ser passados nos registradores r0, r1, etc. (até r3). No registrador r0 novamente colocamos o endereço da string de formatação. Na linha 25 carregamos no registrador r1 o endereço (=numero) da variável numero e na linha 26 carregamos o conteúdo do valor armazenado no endereço de memória armazenado no registrador r1. Por fim, na linha 27 invocamos a função printf. A linha 29 e 30 move a constante 0 (zero em decimal) para o registrador r0 e prepara para voltar a executar o código que invocou a função main. Lembre-se que um programa em linguagem C, em geral possui como ultima linha da função main a instrução return 0 ou exit(0). Este ponto também será descrito em maiores detalhes em uma aula/laboratório futuro. 3 Como compilar seu programa em linguagem assembly Para compilar o seu programa em linguagem assembly do arm você tem duas opções. Você pode utilizar um montador (vamos utilizar o GNU AS) e depois o GCC para que ele faa̧ a linkagem autoamticamente para você ou você pode utilizar o GNU AS e em seguida o GNU LD. Vejamos como fazer cada caso. O primeiro passo é fazer a montagem do arquivo, para isso considere que o 3 código em linguagem de montagem foi escrito e salvo em um arquivo chamado exemplo1.as e que o resultado do processo de montagem será armazenado no arquivo exemplo1.o. Primeiro geramos o arquivo montado (arquivo objeto ou .o): ra999999@arm1:~$ as exemplo1.as -o exemplo1.o e em seguida criamos o arquivo executável utilizando o GNU linker (digite este comando em um linha, ou quebre linha no lugar indicado por uma barra invertida "\"): ra999999@arm1:~$ ld -dynamic-linker /lib/ld-linux.so.3 /usr/lib/crt1.o \ /usr/lib/crti.o -L/usr/lib exemplo1.o -lc /usr/lib/crtn.o -o exemplo1 ou o GCC: ra999999@arm1:~$ gcc exemplo1.o -o exemplo1 Note que o arquivo executável gerado será chamado de exemplo1. Note também que o GCC irá basicamente executar o mesmo comando que você digitaria no exemplo. Você pode executar o programa digitando: ra999999@arm1:~$ ./exemplo1 Digite um numero: 2001 Valor lido: 2001 ra999999@arm1:~$ 4 Referências sobre ARM • Cartão de referência rápida para as instruções ARM: http://infocenter.arm.com/help/ topic/com.arm.doc.qrc0001m/QRC0001_UAL.pdf (ignore as instruções que só são suportadas em versões específicas do ARM, como Thumb, Thumb2, v6 e v7) • Referência da arquitetura ARMv5, utilizada no simulador da disciplina: http://www.scss. tcd.ie/~waldroj/3d1/arm_arm.pdf (Capítulo A4 descreve instrução por instrução) • Infocenter ARM: http://infocenter.arm.com/help/index.jsp • Site com bastante material sobre linguagem de montagem ARM: http://www.coranac.com/ tonc/text/asm.htm (ignorar a parte de Thumb). • Manual do GNU assembler, o montador utilizado: http://sourceware.org/binutils/docs/ as/ • Manual do GNU debugger (o gdb, depurador utilizado): http://sourceware.org/gdb/current/ onlinedocs/gdb/ 4