• Nenhum resultado encontrado

Descrição e análise da implementação em Assembly MIPS da função itoa

N/A
N/A
Protected

Academic year: 2021

Share "Descrição e análise da implementação em Assembly MIPS da função itoa"

Copied!
6
0
0

Texto

(1)

Descrição e análise da implementação em

Assembly MIPS da função itoa

Alana Rocha1, Guilherme Alves2, Guilherme Nunes3 e Luiz Guilherme4

Objetivo e visão geral do documento. Este documento tem o objetivo de analisar detalhadamente a implementação da função itoa em Assembly MIPS e sua execução no simulador PCSPIM, e é organizado da seguinte maneira: (seção 1) apresentação da função itoa e sua respectiva implementação em C, (seção 2) implementação da função itoa em Assembly MIPS com comentários, (seção 3) relação das porções de código Assembly com os trechos equivalentes do código C e (seção 4) apresentação e descrição do funcionamento do simulador PCSPIM.

1. A função itoa(int)

A obtenção da string correspondente a um valor inteiro é uma requisição muito comum em qualquer programa e, devido a esta necessidade, fez-se necessário implementar uma função correspondente e incluí-la na biblioteca padrão C stdlib.h. Tal função tem o identificador itoa.

A implementação da função itoa é composta basicamente de duas rotinas principais, a saber: (a) a primeira faz a conversão e armazena os caracteres correspondente ao inteiro na string de saída em ordem inversa e (b) a segunda faz a inversão dos caracteres na string, ou seja, coloca os caracteres na ordem correta. A figura 1 apresenta um exemplo gráfico de entrada e saída para cada uma das rotinas.

FIGURA 1. Exemplo de execução das rotinas principais da função itoa para o valor -512. Pode-se ainda detalhar a implementação da função itoa como segue:

i. O primeiro bloco de instruções é destinado a tratar números negativos da seguinte maneira: se o valor for negativo, faz-se uma cópia do valor e o armazena na variável sign e em seguida inverte o sinal do valor a ser convertido.

ii. O segundo bloco é responsável por fazer a conversão propriamente dita: realiza-se sucessivas divisões por 10 e armazena o valor do quociente para a próxima iteração, ao resto da operação de divisão é adicionado o valor inteiro correspondente da tabela ASCII ao caractere ‘0’ e armazenado na posição correspondente da string [2].

iii. O último bloco de instruções da rotina itoa adiciona o caractere de sinal negativo na string caso o valor a ser convertido seja negativo, isso é detectado por meio da variável sign que é previamente salva no início da função.

1 Alana Rocha Santos – 11111BCC01, alana_rocha@live.com

2 Guilherme Alves da Silva –11111BCC014, guilhermealves@comp.ufu.br 3 Guilherme Nunes Costa - 11111BCC036, guilhermecjr@hotmail.com

4 Luiz Guilherme de Souza Pelegrini – 11111BCC024, luizguilherme_07@hotmail.com

-512 2 1 5 - \0 int char* - 5 1 2 \0 char* reverse itoa

(2)

iv. Neste estágio a função já fez a conversão, porém armazenou os caracteres na string em ordem inversa. Para fazer a operação de reordenação dos caracteres chama-se a rotina reverse que possui um único bloco de instruções. Esse bloco de instruções basicamente consiste em um lanço que troca os caracteres de lugar na string.

FIGURA 2. Estrutura básica do conjunto de instruções das rotinas itoa e reverse.

A seguir é apresentado o código C completo da função itoa retirado de [1]. Observe que cada rotina de itoa é uma função a parte, ou seja, a primeira rotina corresponde ao código de void itoa (int, char) e a segunda corresponde ao código de void reverse (char *s).

11 void itoa (int n, char *s) { 12 int i, sign; 13 if ((sign = n) > 0) { 14 n = -n; 15 } 16 i = 0; 17 do { 18 s[i++] = n % 10 + ‘0’; 19 } while ((n /= 10) > 0); 20 if (sign < 0) 21 s[i++] = ‘-‘; 22 s[i] = ‘\0’; 23 reverse(s); 24 }

25 void reverse (char *s) { 26 int c, i, j; 27 for (i = 0, 28 j = strlen(s)-1; 29 i < j; i++, j--) { 30 c = s[i]; 31 s[i] = s[j]; 32 s[j] = c; 33 } 34 }

2. Implementação em Assembly MIPS

Abaixo apresentamos o código Assembly, com comentários, correspondente as funções itoa e reverse.

Código Comentário

1 .data

2 hello: .ascii "\nDigite um numero:"

3 newln: .asciiz "\n" 4 str: .space 32

itoa (int, char*) { . . . . . . . . . . reverse (char*); } (1) (2) (3) reverse (char*) { . . . } (4) Trata número negativos

Laço que faz a conversão Adiciona o terminador de string e, se necessário, o sinal de negativo

Laço que inverte os caracteres na string

(3)

5

6 .text

7 reverse: addi $t2, $a0, -1 t2 <- a0 - 1 ; t2 guarda o índice da string

8 lbu $t3, 1($t2) load byte unsigned

9 beqz $t3, end_strlen se t3 == 0 então vai para o end_strlen, ou seja, se a string é vazia

10 strlen_loop: addi $t2, $t2, 1 t2++

11 lbu $t3, 1($t2) t3 <- segunda posição da string

12 bnez $t3, strlen_loop se t3 != 0 então vai volta para strlen_loop 13 end_strlen: bge $a0, $t2, end_reverse se a0 >= t2 então vai para end_reverse ;

esta é a condição de parada do for 14 reverse_loop: lbu $t3, ($a0) t3 <- a0

15 lbu $t4, ($t2) t4 <- t2

16 sb $t3, ($t2) t2 <- t3

17 sb $t4, ($a0) a0 <- t4

18 addi $a0, $a0, 1 a0++

19 addi $t2, $t2, -1 t2--

20 blt $a0, $t2, reverse_loop se a0 < t2 então vai para o reverse_loop 21 end_reverse: jr $31 volta para o itoa

22

23 .globl itoa

24

25 itoa: addi $29, $29, -4 sp--

26 sw $31, 0($29) sp <- ra

27 move $t0, $a0 t0 <- a0 ; t0 é o sign

28 move $t3, $a1 t3 <- a1 ; ponteiro pro inicio do string 29 bgez $a0, non_neg se a0 >= 0 então vai para non_neg 30 sub $a0, $0, $a0 caso contrário a0 <- -a0

31 non_neg: li $t2, 10 t2 <- 10 32 itoa_loop: div $a0, $t2 a0 <- a0/10

33 mfhi $t1 t1 <- a0 % 10

34 mflo $a0 a0 <- a0/10

35 addi $t1, $t1, 48 t1 <- t1 + 48 ; 48 corresponde em ASCII ao caracter '0'

36 sb $t1, 0($a1) a1 <- t1

37 addi $a1, $a1, 1 a1++

38 bnez $a0, itoa_loop se a0 != 0

39 bgez $t0, non_neg2 se t0 >= 0 então vai para non_neg2

40 li $t1, '–' t1 <- '-'

41 sb $t1, 0($a1) t1 ++ '-' ; concatenação

42 addi $a1, $a1, 1 a1++

43 non_neg2: sb $0, 0($a1) a1 ++ 0 ; concatenação >> finaliza string 44 move $a0, $t3 a0 <- t3 ; a0 é ponteiro para o início da

string

45 jal reverse chama a função de reverso

46 lw $31, 0($29) ra <- sp 47 addi $29, $29, 4 sp++ 48 jr $31 retorna ao main 49 50 .globl main 51 main: addi $29, $29, -4 sp++ 52 sw $31, 0($29) sp <- ra 53 li $v0, 4 v0 <- 4

54 la $a0, hello a0 <- &hello

55 syscall chamada de sistema

56 li $v0, 5 v0 <- 5

57 syscall chamada de sistema

58 move $a0, $v0 a0 <- v0

59 la $a1, str a1 <- &str

60 jal itoa itoa(a0)

61 la $a0, str a0 <- &str

62 li $v0, 4 v0 <- 4

63 syscall chamada do sistema

64 la $a0, newln a0 <- &newln

65 syscall chamada do sistema

66 lw $31, 0($29) ra <- sp

67 addi $29, $29, 4 sp--

(4)

Funções especiais. Note que no decorrer do código nos deparamos com uma série de funções não padrão da arquitetura MIPS, tais funções são explicadas a seguir:

lbu – Carrega um byte em um registrador desconsiderando o sinal beqz – Testa se o valor de um registrador igual a zero

bnez – Testa se o valor de um registrador é diferente de zero bgez – Testa se o valor de um registrador é maior ou igual a zero la - Carrega um endereço, de uma variável, em um registrador li – Carrega um valor imediato em um registrador

3. Relação entre implementações

Nesta esta seção relacionamos cada porção de código Assembly MIPS com o respectivo código C das funções itoa e reverse.

FIGURA 3. Função reverse e seus respectivos trechos de código em Assembly.

Assembly MIPS

Linguagem C

Label Código

5 .text

6 reverse: addi $t2, $a0, -1

7 lbu $t3, 1($t2)

8 beqz $t3, end_strlen void reverse (char *s) { 1

9 strlen_loop: addi $t2, $t2, 1 int c, i, j; 2

10 lbu $t3, 1($t2) for (i = 0, 3

11 bnez $t3, strlen_loop j = strlen(s)-1; 4

12 end_strlen: bge $a0, $t2, end_reverse i < j; i++, j--) { 5

13 reverse_loop: lbu $t3, ($a0) c = s[i]; 6

14 lbu $t4, ($t2) s[i] = s[j]; 7

15 sb $t3, ($t2) s[j] = c; 8

16 sb $t4, ($a0) } 9

17 addi $a0, $a0, 1 } 10

18 addi $t2, $t2, -1

19 blt $a0, $t2, reverse_loop 20 end_reverse: jr $31

(5)

FIGURA 4. Função itoa e seus respectivos trechos de código em Assembly.

4. O simulador PCSPIM

SPIM é um simulador autônomo que roda programas na arquitetura MIPS32. Ele lê e executa programas escritos em linguagem assembly. O SPIM também nos fornece um debugger simples e um conjunto enxuto de serviços operacionais. No entanto, ele não executa programas em linguagem de máquina. SPIM implementa quase todo o conjunto de instruções da arquitetura MIPS32, sendo que algumas comparações entre números de ponto flutuante são omitidas. A arquitetura MIPS inúmeras invariantes que se diferem entre si (i.e., a MIPS64 tem capacidade para trabalhar com inteiros e endereços de 64 bits cada), o que significa que o simulador SPIM não irá executar programas em todos os processadores da arquitetura MIPS.

O programa SPIM é composto de quatro segmentos dispostos na janela principal e um console. Cada área tem sua importância. A primeira parte, chamada Registers, ficam os registradores internos do MIPS, independente de serem usados ou não no código aberto. Seus valores são atualizados a cada instrução executada. Podemos ver os valores sendo alterados, facilmente, usando um break point na primeira linha do código executando, então, instrução por instrução.

Na segunda área, Text Segment, fica o código *.asm que foi importado e cada linha é associada com o endereço onde ela se encontra. Algumas instruções podem ser trocadas por instruções equivalentes, mas na mesma linha se encontra mais a direita o código original. A terceira parte, chamada de Data Segment, mostra os segmento de dados do usuário (DATA), a pilha (STACK) e o segmento de dados do kernel (KERNEL DATA). Elas são mostradas em duas colunas: o endereço do bloco de memória e o conteúdo do bloco.

O quarto segmento é o Messages, onde o simulador envia mensagens ao usuário. Ao executar instrução por instrução como é o caso da figura, ele vai mostrando a instrução que

21 .globl itoa

22 itoa: addi $29, $29, -4

23 sw $31, 0($29)

24 move $t0, $a0

25 move $t3, $a1

26 bgez $a0, non_neg

27 sub $a0, $0, $a0 void itoa (int n, char *s) { 11

28 non_neg: li $t2, 10 int i, sign; 12

29 itoa_loop: div $a0, $t2 if ((sign = n) > 0) { 13

30 mfhi $t1 n = -n; 14

31 mflo $a0 } 15

32 addi $t1, $t1, 48 i = 0; 16

33 sb $t1, 0($a1) do { 17

34 addi $a1, $a1, 1 s[i++] = n % 10 + ‘0’; 18 35 bnez $a0, itoa_loop } while ((n /= 10) > 0); 19

36 bgez $t0, non_neg2 if (sign < 0) 20

37 li $t1, '–' s[i++] = ‘-‘; 21

38 sb $t1, 0($a1) s[i] = ‘\0’; 22

39 addi $a1, $a1, 1 reverse(s); 23

40 non_neg2: sb $0, 0($a1) } 24 41 move $a0, $t3 42 jal reverse 43 lw $31, 0($29) 44 addi $29, $29, 4 45 jr $31 Assembly MIPS Linguagem C Label Código

(6)

está sendo executada. E por fim, o console que é a comunicação programa/usuário; onde irão aparecer comandos de leitura de dados e escrita de resultados.

FIGURA 5. Imagem da execução do arquivo itoa.asm no software PC SPIM.

Referências

[1] KERNIGHAN, Brian W.; RITCHIE, Dennis M. The C Programming Language. Upper Saddle

River, New Jersey: Prentice hall, 1978. 228 p.

[2] ASCII Corporation. American Standard Code for Information Interchange Table. In: < http://www.facom.ufu.br/~claudio/Cursos/PP/Docs/full_ASCII_table.pdf>. Acesso em: 26/03/2013.

[3] PATTERSON,D.,HENNESSY,J.L., Organização e Projeto de Computadores: Interface

Hardware/Software, Morgan Kaufmann Series; 4th Edition; 2009;

[4] REED, D. F., MIPS Architecture and Assembly Language Overview. In; <http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm>. Acesso em: 26/03/2013

Referências

Documentos relacionados

É possível afirmar que os fatores motivadores ganhos pessoais, aprendizado e interação social foram relevantes para esse tipo específico de CV, onde pessoas cadastram um projeto

A tendência manteve-se, tanto entre as estirpes provenientes da comunidade, isoladas de produtos biológicos de doentes da Consulta Externa, como entre estirpes encontradas

Estudos sobre privação de sono sugerem que neurônios da área pré-óptica lateral e do núcleo pré-óptico lateral se- jam também responsáveis pelos mecanismos que regulam o

São eles, Alexandrino Garcia (futuro empreendedor do Grupo Algar – nome dado em sua homenagem) com sete anos, Palmira com cinco anos, Georgina com três e José Maria com três meses.

Para al´ em disso, quando se analisa a rentabilidade l´ıquida acumulada, ´ e preciso consid- erar adicionalmente o efeito das falˆ encias. Ou seja, quando o banco concede cr´ editos

Assim sendo, o espaço da estrada é determinante como facilitador de um exercício de uma sexualidade mais plena, aberta e satisfatória, pelo menos para Thelma, e ao

Crisóstomo (2001) apresenta elementos que devem ser considerados em relação a esta decisão. Ao adquirir soluções externas, usualmente, a equipe da empresa ainda tem um árduo

Para separação de água/óleo a membrana recoberta internamente com filme de PEBD contendo 5% de argila organofílica em peso se mostrou mais seletiva do que a