CMP1130 - Linguagens de Montagem
3a Lista de Exercícios
Max Gontijo de Oliveira
Dicas:
• Construa o fluxograma para orientar a programação.
• Dentro dos procedimentos, sempre crie frames de pilha para os procedimentos (instrução
enter). Não se esqueça de destruir o frame de pilha antes de finalizar (instrução leave).
• Dentro dos procedimentos, sempre faça backup dos registradores antes de começar o código (instrução pusha) e restaure o estado dos registradores antes de finalizar o programa
e destruir o frame (instrução popa).
– Caso o procedimento tenha que retornar algum valor via registrador, estabeleça
uma variável local (via pilha utilizando o primeiro parâmetro da instrução enter)
e utilize essa variável para não perder o valor do registrador.
Instruções para programação e compilação
• Não refaça código desnecessariamente. Utilize os procedimentos já criados sempre que
precisar em algum outro procedimento ou programa.
• Você poderá criar procedimentos adicionais, caso julgue útil. Não precisam ser procedimentos genéricos. Podem ser procedimentos específicos, apenas para modularizar melhor.
• Crie um arquivo separado para codificar os procedimentos genéricos que podem ser utilizados em qualquer programa (tais como, leitura de número, impressão de número, impressão de string, leitura de string, etc). Dê um nome ao arquivo, como por exemplo,
lib_nome_aluno.asm.
– Esse arquivo contendo os procedimentos genéricos não terá o procedimento main.
Terá apenas os procedimentos genéricos. Assim, ele não irá gerar um executável.
Todavia, deve ser montado. Mara gerar o arquivo montado, utilize o comando:
nasm -f elf lib_nome_aluno.asm
∗ Esse comando efetua a montagem da biblioteca e gera como saída o arquivo
lib_nome_aluno.o
– Cada procedimento desse arquivo deverá ser declarado como global no topo do arquivo (por exemplo, global ler_int_s, sai_string).
– Para que qualquer procedimento desse arquivo seja visível em outros programas/procedimentos de outros arquivos, é necessário declarar que esses procedimentos são
externos (extern).
• Todos os programas tem extensão .asm e a geração do executável deverá passar por dois
comandos:
nasm -f elf nome_do_programa.asm
– Esse comando efetua a montagem do programa e gera como saída o arquivo
nome_do_programa.o
gcc -o nome_do_programa nome_do_programa.o lib_nome_aluno.o
– Esse comando compila a partir dos arquivos montados (programa e biblioteca) e gera
o executável nome_do_programa.
1. Crie um procedimento em Assembly que se chame ler_int_s que receba por parâmetro (via
pilha) o endereço de uma variável de 32 bits (dword). O procedimento deverá utilizar a função
scanf com o formato "%d" para realizar a leitura de um número inteiro sinalizado e armazenar
na variável cujo endereço foi passado por parâmetro.
2. Crie um procedimento em Assembly que se chame sai_int_s que receba por parâmetro (via
pilha) um número de 32 bits (dword). O procedimento deverá utilizar a função printf com a
string "%d" para imprimir na tela o número inteiro sinalizado passado por parâmetro.
3. Crie um procedimento em Assembly que se chame ler_string que receba por parâmetro (via
pilha) o endereço de uma string (cadeia de bytes). O procedimento deverá utilizar a função gets
(que recebe o endereço da string) para realizar a leitura da string passada por parâmetro.
4. Crie um procedimento em Assembly que se chame sai_string que receba por parâmetro (via
pilha) o endereço de uma string (cadeia de bytes). O procedimento deverá utilizar a função
printf com a string "%s" para imprimir na tela a string passado por parâmetro.
5. Crie um procedimento em Assembly que se chame quebra_linha. Esse procedimento não receberá nenhum parâmetro. Ele deverá imprimir na tela uma quebra de linha. Dica: utilize a função
printf passando uma string declarada no segment .data que tenha o valor 10 (é equivalente
ao "\n"). Por exemplo, quebra db 10,0
6. Crie um procedimento em Assembly que se chame limpa_tela. O procedimento deverá executar
uma chamada ao sistema para limpar a tela no terminal. No Linux, utilize no seu procedimento a
função system com o parâmetro "clear".
7. Crie um procedimento em Assembly que se chame eh_primo que receba por parâmetro (via pilha)
um número inteiro positivo e retorne em EAX 1 caso o número seja primo ou 0 caso contrário.
8. Crie um procedimento em Assembly que se chama media que receba por parâmetro (via pilha)
o endereço de um vetor de dword e a quantidade de elementos do vetor. O procedimento deverá
calcular a média de todos os elementos e retornar a parte inteira da média em EAX.
9. Crie um procedimento em Assembly que se chama fatorial que calcule o fatorial de um número
passado por parâmetro (via pilha). Desafio: Experimente criar o procedimento utilizando um
algoritmo recursivo.
10. Crie um PROGRAMA em Assembly que leia um número inteiro positivo e imprima na tela todos
os números primos entre 1 e o número lido.
11. Crie um PROGRAMA em Assembly que leia um número inteiro positivo (no máximo 14) e calcule
e exiba na tela o fatorial desse número.
12. Crie um PROGRAMA em Assembly que leia todos os 10 elementos (números inteiros sinalizados)
de um vetor de dword previamente declarado no segment .bss. Apos a leitura desses elementos,
calcule a média aproximada por falta (apenas a parte inteira). Por fim, imprima a média, imprima
todos os elementos maiores ou iguais à média e, em seguida, imprima todos os elementos abaixo da
média. A saída deverá seguir o exemplo abaixo:
Média:
25
Acima ou igual à média
32
42
28
35
50
Abaixo da média
15
12
17
20
2
13. Crie um PROGRAMA em Assembly que leia os elementos de duas matrizes de inteiros (dword)
A5×4 e B5×4 e calcule a soma A + B. Considere que ambas as matrizes possuem dimensões iguais
e já foram declaradas no segment .bss
14. Crie um PROGRAMA em Assembly que declare no segment .data uma string contendo uma
representação visual do que seria uma matriz de dimensões 3 × 4 com todos os seus elementos
inicializados com 0. Veja como você pode fazer isso de forma intuitiva.
m a t r i z _ v i s u a l db
db
db
db
db
db
db
"+−−−+−−−+−−−+−−−+" , 1 0 ,
" | 0 | 0 | 0 | 0 | " ,10 ,
"+−−−+−−−+−−−+−−−+" , 1 0 ,
" | 0 | 0 | 0 | 0 | " ,10 ,
"+−−−+−−−+−−−+−−−+" , 1 0 ,
" | 0 | 0 | 0 | 0 | " ,10 ,
"+−−−+−−−+−−−+−−−+" , 1 0 , 0
O programa deverá:
1. imprimir a string matriz_visual na tela;
2. ler um número inteiro variando de 0 à 1 (linha) e armazenar numa variável I (dword);
3. ler outro número inteiro variando de 0 à 2 (coluna) e armazenar numa variável J (dword);
4. ler um terceiro número inteiro variando de 1 à 9 e armazenar em uma variável X (dword);
5. converter o número inteiro X lido em um número no formato caractere e armazenar esse valor
no exato centro da célula da matriz visual representada pela string.
6. limpar a tela e imprimir a string matriz_visual novamente, mas agora, alterada.
Exemplo:
O programa mandará imprimir a string no passo 1 e o resultado inicial será esse:
+−−−+−−−+−−−+−−−+
| 0 | 0 | 0 | 0 |
+−−−+−−−+−−−+−−−+
| 0 | 0 | 0 | 0 |
+−−−+−−−+−−−+−−−+
| 0 | 0 | 0 | 0 |
+−−−+−−−+−−−+−−−+
Se o usuário digitar 1 para a linha I, 2 para a coluna J e 7 para o valor X, quando o programa
mandar imprimir novamente a string matriz_visual, o resultado deverá ser esse:
+−−−+−−−+−−−+−−−+
| 0 | 0 | 0 | 0 |
+−−−+−−−+−−−+−−−+
| 0 | 0 | 7 | 0 |
+−−−+−−−+−−−+−−−+
| 0 | 0 | 0 | 0 |
+−−−+−−−+−−−+−−−+
Download

3ª Lista de Exercícios