ARQUITECTURA DE COMPUTADORES CAPÍTULO II AULA III Março 2014
Índice Instruction Set Revisões Procedimentos Stack Comunicar com pessoas ASCII Programar em MIPS estrutura, input e output Programar em MIPS Mais pseudo-instruções MARS MARS - Exercícios
Instruction Set Architecture é uma interface abstracta entre o hardware e o software que inclui toda a informação necessária para escrever correctamente um programa em linguagem máquina Modelo Sequencial: Fetch PC Descodifica Lê os inputs Executa Escreve os output Next PC Revisões
Formato ISA varia por: Tamanho: fixo, variável, ambos Codificação. MIPS 32 bits tamanho instruções fixo = 32 bits (palavra) 32 registos $t0 a $t9 registos temporários $s0 a $s7 Aritmética: add (add $t0,$s1,$s2) addi (add $t0,$s1,1) sub (sub $t0, $s2,$s1) Revisões
MIPS 32 bits Data Transfer Instructions lw $t0,32($s3) sw $t0,32($s3) Lógica sll $t0,$s0,4 srl $t0,$s0,4 (and, or, nor, xor) Branches condicionais beq $s0,$s1,l1 bne $s0,$s1,l1 Set on less than slt $t0,$s0,$s1 Brances não-condicionais Jump: j ELSE Revisões
MIPS 32 bits Whiles, do while, etc Loop: J Loop Procedimentos Jump and link instruction (JAL) JAL CALCULA Jump register (JR) JR $RA $ZERO = 0 Parâmetros de entrada: $a0, $a1, $a2, $a3 Registos de saída: $v0, $v1 Revisões
if( i == j) f = g + h; else f = g h; Linguagem C Instruction Set Compilador ELSE: EXIT: Revisões bne $s3,$s4, ELSE add $s0,$s1,$s2 j EXIT sub $s0,$s1,$s2 Assembly MIPS Assemblador Código máquina 00010110011101000000000000000010 00000010001100101000000000100000 00001000000100000000000000000100 00000010001100101000000000100010
Procedimento Em qualquer linguagem de programação o uso de funções para organizar, estruturar e optimizar o código é não só comum, como parte fundamental de boas práticas de programação. Uma função ou procedimento é uma camada de abstração que executa determinada tarefa com base num determinado input, devolvendo o output resultante. Em assembly o uso de procedimentos é comum, existindo registos apropriados para os mesmos.
Procedimento O MIPS define uma série de registos que devem ser utilizados em procedimentos, nomeadamente: $a0 a $a3 4 registos para passar parâmetros; $v0 a $v1 2 registos para devolver resultados; $ra 1 registo para retornar ao ponto de origem. A função jump-and-link instruction (jal) permite saltar para um procedimento, guardando automaticamente o registo do ponto de retorno em $ra (return address). A função jump register (jr) é utilizada para saltar para determinado registo. Neste caso, para voltar ao ponto de origem: jr $ra.
Procedimentos - STACK Imaginando que o compilador necessita de mais registos para o procedimento do que 4 registos de entrada e 2 de saída; ou que é fundamental restaurar os valores dos registos do programa após a execução do procedimento, para os valores anteriores. Torna-se fundamental estender os registos para a memória. Para tal, utiliza-se uma estrutura chamada de stack. A stack é uma estrutura de dados organizada segundo last-in-first-out (LIFO). A stack tem um ponteiro para o elemento mais recente, nomeadamente o registo $sp (stack pointer).
As stack são tão comuns que até têm nomenclatura própria. Inserir dados na stack denomina-se Push Remover dados da stack denomina-se Pop Procedimento
int exemplo (int g, int h, int i, int j) { int f; } return f; Instruction Set Compile o seguinte exemplo, mantendo $t1, $t0 e $s0 e: g = $a0; h = $a1; i=$a2; j=$a3; f=$s0 f = (g + h) (i + j) Resolução: Procedimento addi $sp,$sp,-12 sw $t1, 8$sp sw $t0, 4$sp sw $s0, 0$sp add $t0, $a0,$a1 add $t1, $a2,$a3 sub $s0, $t0,$t1 add $v0,$zero,$s0 lw $s0, 0$sp lw $t0, 4$sp lw $t1, 8$sp addi $sp,$sp,12 jr $ra
Procedimento Apesar de no exemplo anterior termos guardado $t0 e $t1, sendo estes registos temporários, o programa não espera que sejam guardados. Registos de $t0 a $t9 não devem ser guardados em stack. Registos de $s0 a $s7 devem ser sempre guardados em stack. Considerando o caso anterior, pouparíamos dois stores e dois loads.
ASCII Desde que os computadores passaram viavelmente a serem comercializados, a substituição de bits por caracteres tornou-se fundamental. Para tal, após vários anos sem qualquer norma, surge o código ASCII. ASCII American Standard Code for Information Interchange Caracteres de 8 bits 256 possibilidades
ASCII
ASCII
ASCII No âmbito da manipulação de bytes, é comum pretendermos carregar ou guardar 1 byte em vez de uma palavra inteira (4 bytes). Para tal, existem em MIPS os comandos lb (load byte) e sb (store byte) que permitem manipular bytes entre a memória e os registos. lb e sb carregam e guardam, respectivamente, um byte nos 8 bits mais significativos (os 8 mais à esquerda). lb $t0,0$sp sb $t0,0$gp
ASCII Os caracteres ASCII são normalmente utilizados em grupo, constituindo sequências. Sequências de caracteres resultam em strings, ou seja, palavras ou frases. Para implementar strings existem 3 técnicas: 1. A primeira posição da string indica o tamanho da mesma. 2. A string é acompanhada de uma variável que indica o tamanho da mesma. 3. A string termina com um caracter especial, utilizado para marcar o seu fim.
ASCII Por exemplo, em linguagem C, utiliza-se a terceira técnica com o 0, que segundo a tabela ASCII é null, a marcar o fim da string..asciiz O Java por seu lado, utiliza a primeira opção, utilizando o primeiro caracter para indicar o tamanho da string. O C++ utiliza a segunda opção, utilizando uma estrutura implícita.
ASCII 1º LEN U A L A B 3 85 65 76 65 66 2º class string { int length; char *text; }; 3º U A L NULL A B 85 65 76 0 65 66
ASCII Apesar do código ASCII vir normalizar a conversão de bits para linguagem humana, a verdade é que existem muitas linguagens e muitos alfabetos, que não o Americano. Com isto surge o Unicode. O Unicode por defeito é de 16 bits, ou seja, UTF- 16, mantendo no entanto a compatibilidade com o código ASCII através do UTF-8 (8 bits). Existem ainda casos de caracteres especiais, onde 16 bits são insuficientes. Nesse caso utiliza-se UTF-32.
ASCII No âmbito do UTF-16, o MIPS suporta o load and store também de sequências de 16 bits, ou seja, de halfwords (meias palavras). Utiliza para isso os comando: Load half (lh $t0, 0$sp) Load half unsigned (lhu $t0, 0$sp) Store half (sh $t0, 0$gp)
A programação em assembly MIPS deve respeitar uma estrutura especifica dividida em duas áreas: 1. Declaração de variáveis 2. Código A declaração de variáveis inicia-se com.data A secção de código inicia-se com.text Programar em MIPS I/O Comentários representam-se por #<comentário>
Programar em MIPS I/O A declaração de variáveis deve seguir a seguinte estrutura: <nome variável>: <tipo> <valor> Ex: var1:.word 3 #cria uma palavra com valor 3 array1:.byte a, b, c #criar um vector com 3 pos array2:.space 81 #cria um vector com 81 bytes não inicializados
Programar em MIPS I/O Comandos de saída em MIPS são efectuados através de serviços de sistema específicos. Para indicar o serviço, o identificador do mesmo deverá ser carregado no registo $v0. Se esse serviço necessitar de argumentos de entrada (inputs) podem ser utilizados os registos $a0, $a1 e $a2. O registo $f12 pode também ser utilizado para virgulas flutuantes.
Programar em MIPS I/O Existem diversos serviços disponíveis no IDE MARS, como por exemplo: Serviço Código em $v0 Argumentos print integer 1 $a0 = integer to print print float 2 $f12 = float to print print double 3 $f12 = double to print print string 4 $a0 = address of nullterminated string to print Consultar o manual do MARS para restantes comandos. Para executar estes serviços chama-se o comando syscall (system call).
Programar em MIPS Pseudo Pseudo-Instruções adicionais: Para além das pseudo-instruções já aqui mencionadas, existem outras a considerar: Pseudo-instrução instrução descrição move $s0,$s1 add $s0,$s1,$zero Move um registo para outro clear $s0 add $s0,$zero,$zero Coloca um registo a zero. not $s0, $s1 nor $s0,$s1,$zero Negação de um registo la $s0, LabelAddr li $s0, IMMED[31:0] lui $s0,labeladdr[31:16]; ori $s0,$s0, LabelAddr[15:0] lui $s0,immed[31:16]; ori $s0,$s0, IMMED[15:0] Carrega um endereço Carrega uma constante imediata
Lui = load upper immediate Carrega os primeiros 16 bits para $s0 e mantêm os restantes a 0 Ori = or immediate Efectua um or de 0 sobre os bits anteriores, carregando os 16 menos significativos. Ex: considere o carregamento de uma constante A = 10101010 10101010 para 32 bits: lui $t0,1010101010101010 -> $t0 = 10101010 10101010 00000000 00000000 Ori $t0,$t0, 1010101010101010 = Programar em MIPS I/O 10101010 10101010 00000000 00000000 ori 00000000 00000000 10101010 10101010 10101010 10101010 10101010 10101010
MARS MIPS IDE
MARS - Exercício Implemente uma contagem decrescente de 5 a 0 que termine na expressão Hello World!!..data.text PRINT: EXIT: txt:.asciiz \n Hello World!! addi $v0,$zero,4 la $a0,txt syscall loop: addi $s1,$zero,0 # i = 0 addi $s2,$zero,5 #j = 5 add $t1,$zero,$s2 sub $t1,$s2,$s1 addi $v0,$zero,1 move $a0,$t1 syscall beq $t1,$zero,print addi $s1,$s1,1 #i = i+1 j loop
Dúvidas e Questões Março 2014