Академический Документы
Профессиональный Документы
Культура Документы
2 Ano 2 Semestre
Aulas Terico-Prticas
I. Linguagem Assembly para o MIPS .............................................................................. 3 1. Introduo ................................................................................................................. 3 2. Operaes Bsicas .................................................................................................... 3 3. Representando Instrues no Computador ............................................................... 7 4. Instrues que Tomam Decises .............................................................................. 9 4.1. If ... Then ...Else .............................................................................................. 10 4.2. Loop ................................................................................................................. 10 4.3. While End While ......................................................................................... 10 4.4. ForEnd For................................................................................................... 11 4.5. Case End Case ............................................................................................ 11 5. Sintaxe do Assembler ............................................................................................. 13 5.1. Directivas de compilao................................................................................. 13 5.2. Pseudo Instrues ............................................................................................ 14 6. SPIM ....................................................................................................................... 14 6.1. Instalao ............................................................................................................. 14 6.2. A Janela do SPIM ................................................................................................ 15 6.3. Os Menus ............................................................................................................. 17 6.4. Chamadas ao Sistema .......................................................................................... 18 7. Procedimentos ........................................................................................................ 19 8. Exerccios ............................................................................................................... 23 Programa 1.................................................................................................................. 24 Programa 2.................................................................................................................. 24 Programa 3.................................................................................................................. 25 Programa 4.................................................................................................................. 26
Jos Rosado
2009/ 2010
2. Operaes Bsicas
Para comandar o hardware de um computador tem de falar a sua linguagem. As palavras que a mquina compreende chamam-se instrues e o alfabeto completo conjunto de instrues (instruction set).
Jos Rosado
2009/ 2010
Pode pensar que as linguagens para as mquinas so to diversas como as dos seres humanos, mas na realidade so bastantes similares j que o hardware construdo utilizando tecnologias e normas idnticas conduzindo assim a uma conjunto de instrues bastante similares para as diferentes plataformas. Vamos focar a nossa ateno sobre o instruction set MIPS que utilizado por exemplo pela NEC, Nintendo, Silicon Graphics e Sony, sendo por isso bastante utilizado tendo sido desenhado nos incios dos anos 80s. Todos os computadores devem estar habilitados a realizar operaes matemticas. Se estas so controladas pelo utilizador este tem que introduzir linhas de cdigo que a mquina entenda. Estas instrues so transmitidas para a mquina atravs de uma linguagem de programao que possui regras prprias que depois de serem compiladas se convertem em linguagem de mquina. A notao por exemplo para a adio a utilizar no assembly para MIPS a seguinte: add a,b,c ao escrever esta linha o utilizador esta a ordenar que seja efectuada a soma de b e c e que o valor resultante seja guardado em a. Se agora pretender fazer f=(g+h) (i+j) deve escrever: add t0,g,h add t1,i,j sub f,to,t1 Estas linhas so apenas representaes simblicas do que realmente vamos fazer. Seguidamente vamos ver como estas representaes so passadas para linguagem real MIPS. Ao contrrio do que acontece com linguagem de programao de alto nvel como o C ou o Pascal, no pode guardas o valor em variveis, mas estes tem que ser guardados em registos. O tamanho dos registos na arquitectura MIPS de 32 bits e como estes conjuntos ocorrem muito frequentemente so lhes dados o nome de palavras (word). A maior diferena entre a programao com variveis e registos que estes tm um nmero finito (tipicamente 32 nas mquinas actuais) o que leva a um tipo de raciocnio na forma de programar. Assim, quando estamos a escrever programas os nossos valores so guardados em registos e a tabela seguinte estabelece a conveno de atribuio de nomes aos registos para uma utilizao mais fcil e um uso especfico.
Nome do registo $zero $at $v0 $v1 $a0 $a1 $a2 $a3 $t0 $t1 $t2 $t3 $t4 $t5 N. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 Utilizao Valor zero (inaltervel) Reservado para o Assembler Avaliao de expresses e resultados de funes Avaliao de expresses e resultados de funes Argumento 1 Argumento 2 Argumento 3 Argumento 4 Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes)
Jos Rosado
2009/ 2010
$t6 $t7 $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $t8 $t9 $k0 $k1 $gp $sp $fp $ra
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Saved Temporary ( preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Temporrio (No preservado durante a chamada de funes) Reservado para p uso do kernel do SO Reservado para p uso do kernel do SO Ponteiro para a rea global (heap) Stack pointer Frame pointer Return Address (usado na chamada a funes )
Sempre que vrias funes so compiladas separadamente necessrio uma conveno de chamada a procedimentos e de utilizao de registos para saber exactamente quais os registos que as funes podem usar e alterar o seu contedo. Voltando ao exemplo anterior este ser escrita da seguinte forma: add $t0,$s1,$s2 add $t1,$s3,$s4 sub $s0,$t0,t1 No mundo da programao e computao nem tudo se resume a estruturas bsicas e elementares como as variveis, mas existem estruturas mais complexas que se chamam tabelas (array). Uma tabela no mais do que um conjunto de campos onde se pode guardar informao possuindo um ndice que serve para aceder a estes campos. Como j vimos o processador apenas pode guardar um conjunto pequeno de dados pelo que sempre que trabalhamos com estruturas mais complexas estas tem que ser guardadas na memria. Temos assim necessidade de saber como se procede transferncia de informao entre o processador e a memria. Para aceder a uma palavra (dado) guardada na memria, a instruo tem que fornecer o endereo de memria onde a informao est guardada. Podemos dizer que a memria uma tabela unidimensional muito grande que possui um ndice que nos permite buscar o endereo onde est guardada a informao que pretendemos. Devido ao endereo utilizado na memria cada endereo de memria est desazado do anterior de quatro unidades. Assim, se pretender aceder ao endereo imediatamente a seguir a um outro tem que multiplicar por 4 o anterior. Vamos agora ver quais so as instrues em MIPS que nos permitem transferir informao da memria para o processador e deste para a memria. A transferncia de dados da memria para o registo feita pela funo lw (load word) e a transferencia do processador para a memria pela funo sw (store word). A sintaxe a seguinte: lw registo destino, endereo sw registo destino, endereo Considere um array A com 100 palavras e pretende somar varivel h o contedo da posio 8 do array. Numa linguagem de alto nvel como por exemplo o C fazia
Jos Rosado
2009/ 2010
g=h+A[8]. Em MIPS tem que introduzir as seguintes instrues, supondo que a base da tabela est em $s3, h em $s2 e o resultado colocado em $s1: lw $t0, 32 ($s3) add $s1, $s2, $t0 # Carrega em t0 o valor da posio 8 do array. # Faz a soma e guarda o resultado
Suponha agora que pretende fazer a seguinte operao: A[12]=h+A[8] Em MIPS fazia, supondo que a base da tabela est guardada em $s3: lw $t0, 32 ($s3) add $t0, $s2, $t0 sw $t0, 48($s3) # Carrega em t0 o valor da posio 8 do array # Faz a soma e guarda o resultado em t0 # Guarda na posio 12 do array o resultado
Os ndices das tabelas esto muitas vezes associados a variveis em vez de constante tal como vimos no exerccio anterior, sendo que este valor vai se modificando medida que o programa vai correndo. Assim, a primeira coisa que tem que fazer colocar o seu programa no endereo certo para poder fazer as transferncias ou carregamentos da informao. Por exemplo vamos implementar a seguinte estrutura. g=h+A[i] assumindo que a tabela A tem 100 palavras e que o registo $s3 base deste array e que as variveis g, h e i esto associadas aos registos $s1, $s2 e $s4 respectivamente. Em MIPS escrevamos o seguinte cdigo: add $t1, $s4, $s4 add $t1, $t1, $t1 add $t1, $t1, $s3 lw $t0, 0 ($t1) add $s1, $s2, $t0 # Guarda em t1 o valor de 2*i #Guarda em t1 o valor 4*i # Guarda em t1 o endereo de A[i] (4*i+$s3) # Carrega em t0 o valor da posio i do array # Faz a soma e guarda o resultado em s1
Jos Rosado
2009/ 2010
Cada segmento desta instruo chamado de campo. O primeiro e o ltimo campos definem a combinao da operao que a mquina deve fazer. O segundo campo o nmero do registo do primeiro operador (17=$s1), o terceiro o nmero do registo do segundo operador (18=$s2) e o quarto o nmero do registo onde se guarda o resultado (8=$t0). A representao em binrio a seguinte: 000000 10001 10010 01000 00000 100000
Os campos anteriores tm nomes para mais facilmente se poder trabalhar, assim: op 6 bits rs 5 bits rt 5 bits 32 bits rd 5 bits shamt 5 bits funct 6 bits
op rs rt rd shamt funct
Operao bsica da instruo Registo do primeiro operador fonte Registo do segundo operador fonte Registo do operador destido Ser visto mais tarde Funo
Este tipo de instrues tem o formato R. Por vezes este formato no satisfaz todas as funes. Por exemplo a instruo lw necessita de dois registos e de uma constante. Esta constante serve para seleccionar elementos de grandes estruturas de dados. No formato anterior esta constante estaria limitada a 32 (25) o que muito pequeno. Foi assim, criado um novo tipo de formato chamado formato I que utilizado pelas funes de transferncias de dados. A sua estrutura a seguinte:
Jos Rosado
2009/ 2010
op 6 bits
rs 5 bits
rt 5 bits
Existe ainda outro formato o J que utilizado para saltos incondicionais. Estas instrues tem a seguinte estrutura: op 6 bits Vejamos agora a tabela seguinte: Endereo 26 bits
op 0 0 op 35 45
rd Reg Reg
shamt 0 0
Funo 32 34
Onde $t1 a base do array e $s2 corresponde a h em assembler era escrito da seguinte forma: lw $t0,1200($t1) add $t0,$s2, $t0 sw $t0, 1200($t1) teremos ento o seguinte conjunto de registos:
op 35 0 43
rs 9 18 9
rt 8 8 8
rd
Funo
0 1200
32
E em binrio temos:
Jos Rosado
2009/ 2010
rd
Funo
01000
100000
Jos Rosado
2009/ 2010
4.2. Loop
Considere o seguinte loop: Loop: g=g+A[i] i=i+j if (ih) go to loop assumindo que o array A tem 100 elementos e que g, h, i e j esto associados a $s1, $s2, $s3 e $s4 respectivamente e que em $s5 tem o valor da base de dados. Em MIPS fazia o seguinte cdigo: salto: add $t1,$s3,$s3 add $t1, $t1, $t1 add $t1, $t1, $s5 lw $t0, 0 ($t1) add $s1, $s1, $t0 add $s3, $s3, $s4 bne $s3, $s2, salto
4.3. While
End While
Os programadores no utilizam a estrutura anterior, mas sim o While... End While. Este ciclo implementa um conjunto de operaes enquanto a declarao se mantiver verdadeira. Considere a seguinte estrutura: While (tabela[i] k) i=i+j
Jos Rosado
2009/ 2010
10
Assumindo que i, j e k esto guardados em $s3, $s4 e $s5 e que a base da tabela est em $s6, a implementao em MIPS ser a seguinte: enquanto: add $t1, $s3, $s3 add $t1, $t1, $t1 add $t1, $t1, $s6 lw $t0, 0($t1) beq $t0,$s5, sair add $s3,$s3,$s4 j enquanto sair: # $t1=i+i # $t1= 4i # $t1= endereo de tabela [i] # $t1 ao valor guardado em tabela [i] # se $t0$s5 vai para sair
4.4. For
End For
Quando est a fazer uma adio e um dos operadores uma constante, utiliza uma instruo especial de adio: addi (add immediate) tendo esta a seguinte sintaxe: addi registo1, registo2, constante Suponha que pretende implementar a seguinte estrutura: For (i = 1; i < j; i++) { k = k + i; } Supondo que i = $s3 j = $s4 k = $s5 A implementao em MIPS ser a seguinte: addi $s3, $zero, 1 ciclo: bge $s3, $s4, sair add $s5, $s5, $s3 addi $s3, $s3, 1 j ciclo sair:
4.5. Case
End Case
O teste de igualdade (beq) ou de desigualdade (bne) bastante til mas por vezes interessa verificar se um valor menor ou maior do que outro. Em MIPS isso feito pelas funes: slt - Set on less than (activa em menor que)
Jos Rosado
2009/ 2010
11
sgt - Set on great than (activa em maior que) A sintaxe a seguinte: Instruo registo1, registo2, registo3 No caso slt registo1, registo2, registo3, temos: Se registo2<registo3 -> registo1=1 Se registo2>registo3 -> registo1=0 Se o registo 2 for menor que o registo 3 ento o registo 1 carregado com 1. Se acontece o inverso no registo 1 carregado o valor 0. A funo sgt faz o mesmo s que utiliza para comparao o maior que. J vimos o efeito do salto incondicional, contudo em assembler possvel fazer saltos condicionais (jr) para um endereo especifico de um registo e no para o label. A sintaxe a seguinte: jr registo
Considere a seguinte condio: Switch (k) { Case 0: f=i+j; break; Case 1: f=g+h:break; Case 2: f=g-h: break; Case 3: f=i-j;break } Assumindo que as seis variveis esto guardadas em $s0 a $s5, o cdigo em MIPS ser o seguinte: slt $t3, $s5, $zero bne $t3, $zero, sair addi $t2, $zero, 4 slt $t3,$s5,$t2 bne $t3, $zero, sair # testa se k<0 # se K<0 vai para sair # Coloca no registo $t2 o valor 4 # testa se k>4 # se K>= 4 vai para sair
Como estamos a utilizar a varivel k como ndex da tabela de palavras, temos que fazer o seguinte: add $t1, $s5,$s5 add $t1, $t1,$t1
Jos Rosado
2009/ 2010
12
Assumindo que as quadro palavras esto guardadas sequencialmente na memria e que o endereo de inicio est em $s6, temos: add $t1, $t1, $s6 lw $t0, 0($t1) jr $t0 L0: add $s0, $s3, $s4 J Sair L1: add $s0, $s1, $s2 J Sair L2: sub $s0, $s3, $s4 J Sair L3: sub $s0, $s1, $s2 J Sair Sair: # salta consoante o valor de $t0
5. Sintaxe do Assembler
Um programa em linguagem assembly composto por directivas de compilao, instrues e pseudo instrues.
Jos Rosado
2009/ 2010
13
Indica o incio de uma string que o assembler deve traduzir para os cdigos ASCII respectivos O mesmo que a anterior mas a string terminada pelo caracter nulo (0x00) Indica que os prximos dados devem ser alinhados em endereos mltiplos de 2n Segue-se uma lista de valores a colocar cada um num byte Segue-se uma lista de valores a colocar cada um numa word
Ajuda Programa
Jos Rosado
2009/ 2010
14
O SPIM tem cinco janelas onde pode verificar como o seu programa est a correr: 1. Registers mostra os valores de todos os registos sendo actualizada medida que o programa vai correndo. 2. Text segments mostra as instrues do seu programa e o cdigo de sistema que carregado automaticamente. Cada instruo surge da seguinte forma: [0x00400000] 0x8fa400000 lw $4, 0($29) ; 89:lw $a0, 0($sp) O primeiro nmero da linha o valor em hexadecimal do endereo de memria da instruo. O segundo a codificao em hexadecimal da instruo. Terceiro item a instruo em que por exemplo os registos surgem com o seu nmero e no com o nome associado. E por fim, depois do ; surge a sua instruo onde o primeiro nmero indica a linha do ficheiro que est a correr. 3. Data segments- Mostra o segmento de dados em hexadecimal. Corresponde s reas de memria onde esto os dados manipulados pelo programa. Essas reas so: Data: Comea em 1000 0000h. Contm os dados declarados no programa por exemplo em directivas como .asciiz, .db, .dw, e que so acedidos pelas instrues de load e store. Stack: Comea em 7FFF FFFFh e contm a Pilha. O stack cresce para baixo, isto e, para endereos menores. 4. Messages utilizado para dar algumas mensagens do estado da sua simulao. 5. Consola Esta a janela onde surgem os resultados do seu programa.
Jos Rosado
2009/ 2010
15
As primeiras instrues do Text Segment fazem a ligao entre o sistema e o nosso programa. O salto para o incio do nosso programa faz-se com a instruo jal main. Em seguida comea o cdigo do nosso programa a partir do endereo 0x0040 0020.
Jos Rosado
2009/ 2010
16
6.3. Os Menus
Para testar os seus programas no SPIM e porque o programa no tem um editor de texto, deve escreve-los no bloco de notas e grava-los com a extenso s ou asm. Depois de escrever o programa tem que ir ao menu File e escolher Open e indicar onde est o ficheiro que deseja simular no SPIM. Ao fazer isto as diferentes janelas do programa esto agora preenchidas com valores que nos servem para verificar como o nosso programa est a correr. Quando est a efectuar uma simulao tem os seguintes menus: FILE Open Abre um ficheiro de texto com o seu programa Save Log File Grava um ficheiro de texto com o estado actual da sua simulao Quit Sai do SPIM SIMULATER Clear Registers coloca todos os registos a zero (0x00000000). Reinitialize - limpa os registos e a memria e recomea a simulao Reload reinicializa o simulador e volta a carregar o ficheiro do programa. Go Corre o programa. Break/Continue se o programa est a correr faz uma pausa. No caso de este j se encontrar em pausa continua a execuo. Single Step executa o programa instruo a instruo. Multiple Step... executa o programa com um nmero de instrues definido pelo utilizador. Breakpoints... insere um ponto de paragem na execuo num endereo definido pelo utilizador. Set Value... permite carregar um dado registo com um valor. Display symbol table Mostra a tabela de simulao na janela de mensagens. Settings... Mostra a janela de configurao WINDOW Tem o conjunto de opes que permite arrumar as janelas e navegar. Tem ainda uma opo que permite limpar a consola que bastante til. HELP Permite correr a ajuda online que vem com o programa.
Jos Rosado
2009/ 2010
17
Funo Imprime um valor inteiro na consola Imprime um valor em virgula flutuante na consola Imprime um valor em virgula flutuante de preciso dupla na consola Imprime uma string na consola L um valor inteiro. O valor digitado na consola. L um valor em virgula flutuante. O valor digitado na consola. L um valor em virgula flutuante de preciso dupla. O valor digitado na consola. read_string L uma string da consola. sbrk Retorna um ponteiro para um bloco de memria com N bytes (N = argumento em $a0) exit Termina o programa e retorna o controlo ao sistema Servio Cdigo Argumentos Resultado em $v0 print_int 1 $a0 = valor inteiro print_float 2 $f12 = valor em vrgula flutuante print_double 3 $f12 = valor em vrgula flutuante de preciso dupla print_string 4 $a0 = endereo do incio da string read_int 5 Valor inteiro em $v0 read_float 6 Valor em vrgula flutuante em $f0 read_double 7 Valor em vrgula flutuante de preciso dupla em $f0 read_string 8 $a0 = endereo do buffer $a1 = n. de caracteres a ler sbrk 9 $a0 = n. de byte de memria Endereo do bloco de requisitados ao sistema memria em $v0 exit 10 Para ver como pode utilizar as chamadas ao sistema, considere o seguinte exemplo:
Jos Rosado
2009/ 2010
18
Pretendemos um programa que na consola escreva a seguinte frase A resposta igual a 5 O cdigo que teramos que escrever era o seguinte: .data str: .asciiz A resposta igual a 5 .text li $v0,4 la $a0, str syscall O resultado ser surgir a frase escrita na consola do simulador. #Indica que vai fazer uma chamada print_string # Carrega o argumento de entrada
7. Procedimentos
Um procedimento ou sub-rotina uma ferramenta que os programadores utilizam para estruturar o programa permitindo ainda uma melhor compreenso do mesmo e a reutilizao de cdigo. Para as chamadas de procedimentos deve seguir uma conveno que estabelece as seguintes regras: 1. Como so passados os parmetros para as funes; 2. Como so devolvidos os valores de retorno; 3. Quem responsvel por preservar os valores dos registos. Assim, temos: O procedimento que chama outro deve, imediatamente antes de cham-lo: 1. Passar os quatro primeiros argumentos nos registos $a0 a $a3 e os restantes, se os houver, na pilha por ordem inversa; 2. Guardar os registos que quer que sejam preservados 3. Chamar o procedimento com a instruo jal (Jump and Link) o endereo de retorno fica no registo $ra. O procedimento chamado deve, logo no incio: 1. Arranjar espao na pilha para o quadro de pilha onde vai guardar os seus dados temporrios (subtraindo o tamanho do quadro ao $sp); 2. Guardar os registos que devem ser preservados na chamada e a funo necessita de os usar ($s0 a $s7, $fp, $ra); 3. Estabelecer o $fp, somando o tamanho do quadro de pilha ao $sp. O procedimento chamado deve, imediatamente antes de terminar: 1. Colocar os valores de retorno em $v0 e $v1; 2. Restaurar todos os registos preservados na pilha; 3. Libertar o espao do quadro de pilha (somando o tamanho do quadro de pilha ao $sp);
Jos Rosado
2009/ 2010
19
4.
Para fazer saltos para procedimento temos que utilizar a instruo jal que tem a seguinte sintaxe: jal nome do procedimento Vamos agora ver alguns exemplos da construo de procedimentos: Consideremos o seguinte procedimentos: int exemplo (int g, int h, int i, int j) { int f f=(g+h) (i+j) return f; } Assumindo que g, h, i e j correspondem aos registos registos $a0, $a1, $a2 e $a3 e que f corresponde a $s0, em MIPS o procedimento teria o seguinte cdigo: exemplo: addi $sp, $sp, -12 sw $t1, 8($sp) sw $s0, 4($sp) sw $s1, 0($sp) add $s1, $a0, $a1 add $t1, $a2, $a3 sub $s0, $s1, $t1 # Necessito agora de passar o valor de f add $v0, $s0, $zero # Antes de regressar necessrio colocar os valores anteriores dos registos antes de correr o procedimento: lw $t1, 8($sp) lw $t0, 4($sp) lw $s0, 0($sp) addi $sp, $sp, 12 # O procedimento acaba com um salto para o endereo de retorno jr $ra Para complicar algo as coisas, por vezes ou melhor na maioria das vezes, os procedimentos chamam outros procedimentos. Quando isto acontece deve ter em ateno a utilizao dos endereos de retorno. Considere o seguinte exemplo: 20 # guarda o valor de $t1 # guarda o valor de $t0 # guarda o valor de $s0 # cria espao na pilha para 3 itens # guarda o valor de $t1 # guarda o valor de $t0 # guarda o valor de $s0
Jos Rosado
2009/ 2010
int fact (int n) { if (n<1) return (1) Else return (n*fact(n-1)) } Este procedimento calcula o factorial de um nmero. Em MIPS este procedimento, considerando que n est em $a0, era escrito da seguinte forma: fact: addi $sp,$sp,-16 sw $ra, 12($sp) sw $a0, 8($sp) sw $t0, 4($sp) sw $t2, 0 ($sp) # Guarda espao na pilha para 4 itens # Guarda o endereo de retorno # Guarda o argumento n # Guarda o valor de t0 # Guarda o valor de t2
Quando o procedimento chamado pela primeira vez, a instruo sw guarda o endereo no programa que chama o procedimento. addi $t2, $zero, 1 slt $t0,$a0,$t2 beq $t0, $zero, salto1 addi $v0, $zero,1 lw $t0, 4($sp) lw $t2, 0 ($sp) addi, $sp, $sp,16 jr $ra procedimento salto1 : addi $a0, $a0, -1 jal fact argumento n=n-1 lw $ra, 16($sp) lw $a0, 8($sp) addi $sp, $sp, 16 Seguidamente o valor $v0 ser o produto do antigo argumento $a0 e o valor actual. Em MIPS a multiplicao dada pela seguinte instruo: Mult registo 1, registo 2, registo 3 mult $v0, $a0, $v0 # Restaura o valor de t0 # Restaura o valor de t2 # Coloca o ponteiro da pilha no local inicial # Salta para o endereo onde foi chamado o #a0 = n-1 # Volta a chamar o procedimento mas agora com o # Restaura o endereo de retorno # Restaura o argumento n # Se n>= vai para salto 1
Jos Rosado
2009/ 2010
21
jr $ra
Para concluir esta primeira abordagem s chamadas de procedimentos e a forma como tudo funciona, vamos fazer o seguinte exerccio: Tem uma tabela constituda por n nmeros inteiros e pretende criar um procedimento que a ordene. A primeira abordagem a este problema deve ser determinar quantos procedimentos devo utilizar para obter o efeito desejado. Parece lgico que devem existir dois procedimentos: Um para determinar se a posio v[i] > v[i+1] e outro para no caso de isto se verificar trocar as duas posies. Sejamos ento como deveria ficar o segundo procedimento. Em C teria a seguinte estrutura: troca (int v[], int k) { int temp temp=v[k] v[k]=v[k+1] v[k+1]=temp } O segundo ficava em C da seguinte forma: ordena (int v[], int n) { int i,j for (i=0; i<n); i=i+1) { for (j=i-1;j>0 and v[j]>v[j+1]; j=j-1) {troca (v,j); } } } Assumindo que os parmetros endereo base da tabela V e K so passados em $a0 e $a1, em MIPS deveria escrever as seguintes linhas de cdigo: troca: add $t1,$a1, $a1 add $t1, $t1, $t1 add $s1, $a0, $t1 lw $s2, 4($s1) lw $s3, 0($s1)
Jos Rosado
2009/ 2010
22
sw $s2,0($s1) sw $s3, 4($s1) jr $ra I=>$s0 J=>$s1 ordena: blt $s0, $zero, sair 1 ciclo1: bge $s0, $s3, sair1 ciclo 2 ble $s1,$zero, sair2 add $t1, $s1, $s1 add $t1, $t1, $t1 add $t2, $t1, $s2 lw $t3, 0 ($t2) lw $t4, 4 ($t2) slt $t0, $t4, $t3 beq $t0, $zero, sair 2 move $a0, $s2 que vai ser chamado move $a1, $s1 que vai ser chamado jal troca addi $s1, $s1, -1 j ciclo 2 sair 2: addi $s0, $s0, 1 j ciclo 1 sair 1: jr $ra n=>$s3
Suponha que as variveis so passadas nos seguintes registos: Base da tabela =>$s2
#i<0 sai do programa # Vai para sair 1 se $s0$s3 (in) # Vai para sair 2 se $s1<0 (j<0) # t1=2j # t1 = 4j # t3 =v[j] # t4 =v[j+1] # Se t4 t3 vai para sair 2 # Primeiro parmetro para o procedimento # Segundo parmetro para o procedimento
8. Exerccios
Jos Rosado
2009/ 2010
23
Programa 1
Pretendemos um programa que escreva na consola a frase Ol Mundo. Esse programa deve ser gravado com o nome de primeiro.asm. Deve depois testar esse programa no SPIM e ver o resultado. O cdigo em MIPS o seguinte: msg: .data # definies para o segmento de dados .asciiz Ol Mundo .text .globl main main: li $v0, 4 la $a0, msg syscall sair: A instruo lw registo1, registo2 uma pseudo instruo porque usa um modo de endereamento suportado apenas pelo SPIM. Assim por exemplo a instruo lw $t1, alfa transforma em duas instrues: lui lw $1, 4097 $8, 0($1) # carrega o cdigo do servio print_string # carrega o endereo do incio da string # chama o servio # a mensagem aparece na consola do SPIM
Estas duas instrues so ambas nativas do MIPS. A primeira carrega no registo $1 ($at) o valor 4097 que um valor que o assembler j calculou ( o endereo de memria onde a word foi carregada). A segunda instruo l o valor guardado em memria para o registo $8 ($t0).
Programa 2
Pretendemos um programa leia os valores 4 e 20 de uma tabela e que os substitua pela sua soma e pela sua subtraco. Esse programa deve ser gravado com o nome de segundo.asm. Deve depois testar esse programa no SPIM e ver o resultado. O cdigo em MIPS o seguinte: .data .align 2 valores: .word 4, 20 .text .align 2 .globl main main: la
Jos Rosado
$t4, valores
2009/ 2010
24
lw lw add sw sub sw j
$t0, 0($t4) $t1, 4 ($t4) $t2, $t0, $t1 $t2, 4 ($t4) $t3, $t1, $t0 $t3, 0 ($t4) $ra
# termina
Programa 3
Pretendemos um programa leia da consola um valor inteiro e que o some e o subtraia ao valor e 20 de uma tabela. Deve depois mostrar na consola os resultados. Antes de pedir um nmero deve colocar a mensagem Qual o nmero que deseja - e quando apresentar os resultados deve antes colocar as mensagens: A soma - e a A diferena -. Esse programa deve ser gravado com o nome de terceiro.asm. Deve depois testar esse programa no SPIM e ver o resultado. O cdigo em MIPS o seguinte: .data .align 2 valores: .word 0, 20 msg: .asciiz "Digite o nmero - " msg1: .asciiz "A soma - " msg2: .asciiz "A diferena - " .text .align 2 .globl main main: li $v0, 4 # carrega o cdigo do servio print_string la $a0, msg # carrega o endereo do incio da string syscall # chama o servio li $v0, 5 # l inteiro syscall la $t4, valores lw $t0, 4($t4) # le o 4 para $t0 add $t2, $t0, $v0 # Soma a 20 o nmero sub $t3,$t0, $v0 # Subtrai a 20 o nmero sw $t3, 0($t4) # Guarda o valor da soma sw $t2, 4($t4) # Guarda o valor da soma li $v0, 4 # Carrega o cdigo do servio print_string la $a0, msg1 # Carrega o endereo do incio da string syscall li $v0, 1 move $a0, $t2 syscall li $v0, 4 # Carrega o cdigo do servio print_string
Jos Rosado
2009/ 2010
25
Programa 4
Pretendemos um programa que calcule o factorial de um nmero introduzido pelo utilizador Deve depois mostrar na consola os resultados. Antes de pedir um nmero deve colocar a mensagem Qual o nmero que deseja - e quando apresentar o resultado deve antes colocar a mensagem: O factorial - . Esse programa deve ser gravado com o nome de quarto.asm. Deve depois testar esse programa no SPIM e ver o resultado. O cdigo em MIPS o seguinte: .data msg: .asciiz "Digite o nmero - " msg1: .asciiz "O factorial " .text .globl main main: li $v0, 4 # Carrega o cdigo do servio print_string la $a0, msg # Carrega o endereo do incio da string syscall # Chama o servio li $v0, 5 # L inteiro syscall move $a0, $v0 # Coloca o n como parametro de entrada jal fact # Chama o procedimento li $v0, 4 # Chama o servio la $a0, msg1 # Carrega o endereo do incio da string syscall li $v0, 1 # Carrega o cdigo do servio print_int move $a0, $v1 # Coloca em $a0 o valor de sada do procedimento syscall j sair # Sai do programa fact: addi $sp,$sp,-32 sw $ra, 16($sp) sw $fp, 12($sp) addu $fp, $sp, 16 sw $a0, 8($sp) sw $t0, 4($sp) sw $t2, 0 ($sp) addi $t2, $zero, 1 slt $t0,$a0,$t2 beq $t0, $zero, salto1 # Guarda espao na pilha # Guarda o valor de $sp # Guarda o registo FP # Inicializar o registo $fp # Guarda o argumento n # Guarda o valor de t0 # Guarda o valor de t1
Jos Rosado
2009/ 2010
26
addi $v1, $zero,1 lw $t0, 4($sp) lw $t2, 0 ($sp) addi, $sp, $sp,32 jr $ra procedimento salto1 : addi $a0, $a0, -1 jal fact argumento n=n-1 lw $ra, 16($sp) lw $fp, 12($sp) lw $a0, 8($sp) addi $sp, $sp, 32 mul $v1, $a0, $v1 jr $ra sair:
# Restaura o valor de t0 # Restaura o valor de t2 # Coloca o ponteiro da pilha no local inicial # Salta para o endereo onde foi chamado o #a0 = n-1 # Volta a chamar o procedimento mas agora com o # Restaura o endereo de retorno # Restaura o valor de $fp # Restaura o argumento n # Liberta o espao na pilha # Faz a multiplicao #Regresso ao programa chamador
Jos Rosado
2009/ 2010
27