Exercício do Assembly x86 ocorrência de um caractere

Dezembro 2016



Introdução

Este pequeno exercício de linguagem de montagem x86 visa às arquiteturas x86 (Processadores Intel e AMD de 32 bits) e utiliza a sintaxe Nasm, um "assembly" livre, gratuito e irrestrito em diversas plataformas como Windows ou Linux.
Da mesma forma as funções externas são utilizados a partir da biblioteca C padrão.
Então, você não terá problemas com a sua máquina para fazer este exercício: ele não depende do sistema operacional utilizado. Ele só dependente da arquitetura x86. Para usar o Nasm, a fim de testar esse exercício, você encontrará um tutorial para usar/instalar o Nasm no Windows e no Linux, clicando aqui.

Noções abordadas neste exercício

  • Escrita de uma função com gestão dos parâmetros de entrada
  • Gestão de tabelas

Enunciado

Imaginemos uma tabela de caracteres (que não se termina, obrigatoriamente, com 0). Temos o seu tamanho e queremos testar a presença de um determinado caractere nesta tabela. O objectivo será o de entrar uma função que toma como entrada uma tabela de caracteres, seu tamanho e um caractere. Se este caractere estiver presente na tabela, retornaremos um valor diferente de zero, caso contrário, retornaremos a zero.

Veja o que dará esta função em C:
//O protótipo desta função 
int está_na_tabela(char *tabela int tamanho, char c);
//Exemplo de uso:
char tab[] = {'n', 'e', 'u', 'e'};
está_na_tabela(tab, sizeof(tab), 'u'); //Retornará outra coisa além do 0
está_na_tabela(tab, sizeof(tab), 'a'); // Retornará 0


Você deverá inserir este código:
extern printf 

section .data
tabela db 'dadedidadedavivoufufifamasibifisaz'
sim db 'sim', 10, 0
não db 'não', 10, 0

section .text
global main

está_na_tabela:
;Insira seu código aqui!


main:
push ebp
mov ebp, esp

;Vamos testar se m está presente na tabela
push dword 'm'
;O comprimento da tabela (aqui 34)
push dword 34
;Endereço da cadeia no eax
push tabela

;Apelo de está_na_tabela com o endereço da tabela,
;seu tamanho, e o valor a ser procurado
call está_na_tabela
teste eax, eax
jnz está_presente ;Se eax != 0 então exibimos sim
push não ;Se não exibiremos não
jmp exibir
;Exibir a cadeia com printf
está_presente:
push sim
exibir:
call printf

mov eax, 0
leave
ret


Vamos lá! Pense um pouco, se necessário. Faça uma pesquisa sobre as instruções em relação às cadeias. Não há indícios para este exercício!

Correção

Veja uma solução:
está_na_tabela: 
;Recuperamos o endereço da tabela (primeiro parâmetro) em edi
mov edi, [esp + 4]
; Recuperamos o tamanho da tabela (segundo parâmetro) em ecx
mov ecx, [esp + 8]
;Recuperamos o caractere a ser encontrado (terceiro parâmetro) em eax
mov eax, [esp + 12]

;Busca do caractere
repne scasb
;Se o flag ZERO (ZF) está em 1 é que encontramos o caractere
;Se não é que não o encontramos
;Então basta entrar o valor de ZF em eax
mov eax, 0
;Si ZF = 1 então al = 1 (al sendo 8 bits inferior a eax)
setz al

ret

Explicação

O objetivo é o de você utilizar a combinação das instruções do tipo "rep" et "scas". Aqui nós usamos "repne" . Esta instrução repete a instrução que a segue decrementando ecx a cada repetição. Este circuito termina quando ecx = 0, ou quando o flag Zero (ZF) é a 1. A instrução scasb, entretanto, busca a presença de um caractere (alojado em al, parte inferior do eax) no local da memória apontada pelo edi. Se al é igual ao valor apontado pelo edi, então o flag zero é definido como 1. Então, em todos os casos, o edi é incrementado por 1.

Veja o que acontece, já que, na verdade, o que acaba de ser explicado não é muito convincente:

ZF = 0 
ecx = comprimento
eax = caractere
edi = tabela
//Circuito que representa o "repne scasb"
Quando ecx != 0 ET ZF = 0 Fazer
Si al == [edi] Então
ZF = 1
FinSi
ecx = ecx - 1
edi = edi + 1
Fim EnquantoQue

eax = 0
//Condição que representa o "setz"
Si ZF = 1 Então
eax = 1
FinSi


Pronto!

Veja também :
Este documento, intitulado « Exercício do Assembly x86 ocorrência de um caractere »a partir de CCM (br.ccm.net) está disponibilizado sob a licença Creative Commons. Você pode copiar, modificar cópias desta página, nas condições estipuladas pela licença, como esta nota aparece claramente.