Ejercicio de ensamblador x86: ocurrencia de un carácter

Diciembre 2016



Introducción

Este pequeño ejercicio de ensamblador es para las arquitecturas x86 (procesador Intel y Amd 32 bits) y utiliza la sintaxis de Nasm, un ensamblador libre, gratuito y que puede ser utilizado en diferentes plataformas como Windows y Linux.
Las funciones externas utilizadas son sacadas de la biblioteca C estándar.

De este modo no tendrás problemas ligados a la maquina que utilizas para hacer este ejercicio: no depende del sistema operativo utilizado. Únicamente depende de la arquitectura x86.

Nociones abordadas en este ejercicio

  • Escritura de una función con gestión de parámetros de entrada
  • Gestión de matrices

Enunciado

Supongamos que tenemos una matriz de caracteres (que no termina necesariamente en 0). Sabemos su tamaño y desearíamos poder comprobar la presencia de un carácter determinado en esta matriz. Por lo tanto, el objetivo será crear una función que tome como entrada una matriz de caracteres, su tamaño y un carácter. Si este carácter está presente en la matriz, la función devolverá un valor diferente de cero, si no devuelve cero.

Esta seria la función en C:
//El modelo de esta función
int esta_en_la_matriz (char *matriz, int tamaño, char c);
//Ejemplo de uso:
char tab[] = {'n', 'e', 'u', 'e'};
esta_en_la_matriz (tab, sizeof(tab), 'u'); //Devolverá algo diferente a 0
esta_en_la_matriz (tab, sizeof(tab), 'a'); // Devolverá 0

Será necesario insertar este código dentro:
<code>extern printf

seccion .data
matriz db 'dadedidadedavivoufufifamasibifisaz'
si db 'si', 10, 0
no db 'no', 10, 0

seccion .text
global main

esta_en_la_matriz:
;Inserte el código aquí!!


main:
push ebp
mov ebp, esp

;Vamos a verificar que m esté presente en la matriz
push dword 'm'
;La longitud de la matriz (aquí 34)
push dword 34
;Dirección de cadena en eax
push matriz

;Llamado de esta_en_la_matriz con la dirección de la matriz,
;su tamaño, y el valor a buscar
call esta_en_la_matriz
test eax, eax
jnz esta_dentro;Si eax != 0 entonces mostrar sí
push no ;Si no mostrar no
jmp mostrar
;Mostrar la cadena con printf
esta_dentro:
push si
mostrar:
call printf

mov eax, 0
leave
ret


Listo! Piensa unos cuantos minutos si es necesario. Haz una búsqueda sobre las instrucciones en relación a las cadenas.

Solución

Aquí una solución:
esta_en_la_matriz:
;Obtenemos la dirección de la matriz (primer parámetro) de edi
mov edi, [esp + 4]
;Obtenemos el tamaño de la matriz (segundo parámetro) de ecx
mov ecx, [esp + 8]
;Obtenemos el carácter a encontrar (tercer parámetro) de eax
mov eax, [esp + 12]

;Búsqueda del carácter
repne scasb
;Si el flag ZERO (ZF) esta en 1 es que se ha encontrado el carácter
;Si no es que no se ha encontrado
;Por lo tanto basta con poner el valor ZF en eax

mov eax, 0
;Si ZF = 1 entonces al = 1 (al siendo los 8 bits de menor peso de eax)
setz al

ret

Explicación

El objetivo era de utilizar la combinación de instrucciones de tipo “rep” y “scas”. Aquí hemos utilizado “repne”. Esta instrucción repite la instrucción que le sigue disminuyendo ecx en cada iteración. Este bucle se detiene cuando ecx=0 o cuando el Flag Zero (ZF) es 1. En cuanto a la instrucción scasb, busca la presencia de un carácter (almacenado en al, parte baja de eax) en el espacio de memoria señalado por edi. Si al es igual al valor señalado por edi, entonces el Flag Zero se pone en 1. Luego en todos los casos, edi es aumentado en 1.
Aquí vemos lo que pasa:
ZF = 0
ecx = longitud
eax = carácter
edi = matriz
//Bucle que representa "repne scasb"
Mientras ecx != 0 ET ZF = 0 Hacer
Si al == [edi] Entonces
ZF = 1
FinSi
ecx = ecx - 1
edi = edi + 1
FinMientras

eax = 0
//Condición que representa el "setz"
Si ZF = 1 Entonces
eax = 1
FinSi


Y listo!

Consulta también :
El documento «Ejercicio de ensamblador x86: ocurrencia de un carácter» de CCM (es.ccm.net) se encuentra disponible bajo una licencia Creative Commons. Puedes copiarlo o modificarlo siempre y cuando respetes las condiciones de dicha licencia y des crédito a CCM.