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.
Nota: Para utilizar nasm a fin de testear este ejercicio, haz clic
aquí para ver un tutorial de uso/instalación de nasm para Windows y Linux.
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!
Véase también
Comunidad de asistencia y consejos.
El artículo original fue escrito por
kilian. Traducido por
Carlos-vialfa.