Práctica Strings (Organización del Computador II)

De Cuba-Wiki
Revisión del 04:30 8 oct 2006 de 201.235.224.78 (discusión) (→‎Ejercicio 4)
(difs.) ← Revisión anterior | Revisión actual (difs.) | Revisión siguiente → (difs.)


Ejercicio 1

Dado un string, armar una rutina que calcule la longitud.

  1. Comparar dos Strings, no hay observaciones sobre los dos strings, es decir no se detalla si son de igual longitud, ni si son vacíos, es decir chequear todos los casos.
  2. Generar una rutina que permita comprobar si en un string determinado, se encuentra incluida
    1. un carácter
    2. una palabra
    3. una frase

Item b

Puede utilizarse el codigo a continuacion correspondiente al subitem 3 para los dos anteriores.

Primero calcula la longitud de los dos strings, y despues recorre el contenedor para ver si encuentra la primera ocurrencia del buscado. Una vez encontrada, salva ese estado y empieza a compararlos. Devuelve 1 si lo encuentra, 0 si no.

global buscar

section .text

%define strA [ebp + 8]
%define strB [ebp + 12]

%define ptrA esi
%define ptrB edi

%define longA ebx
%define longB [ebp - 16]

;Busca el string A en el string B

buscar:
	;Inicio stack frame
	push ebp
	mov ebp, esp
	push esi
	push edi
	push ebx
	sub esp, 4
	
	;Calculo longitud de A
	cld
	mov edi, strA
	xor eax, eax
       xor ebx, ebx
	long1:
		inc ebx
		scasb
		jne long1
	dec ebx			;Guardo en ebx la longitud de A
 
 
	;Calculo longitud de B
	mov edi, strB
	xor ecx, ecx
	long2:
		inc ecx
		scasb
		jne long2
	dec ecx			;Guardo en ecx la longitud de B
	mov longB, ecx		;Y en la stack
 	
 
	;Busco primer caracter de A en B
 
	mov ptrB, strB	;edi apunta a B
	mov ptrA, strA	;esi apunta a A
	mov eax, [ptrA]	;Cargo en eax el 1er caracter de strA
 
iter:	repne scasb	;Busca en B hasta encontrar el 1er caracter de A o terminar B
 
	cmp ecx, 0x0	;Si termino de buscar en el string, salgo
	je false
 	
	cmp ecx, longA	;Comparo long de B y de A
	jl false	;Si longB<longA, no puede estar A contenido en B
  	
	mov edx, ptrB	;Guardo el estado del puntero a B
	mov longB, ecx	;Guardo la longitud restante de B
	mov ecx, longA	;Cargo en el contador la long de A
 	
	repe cmpsb	;Compara A y B mientras sean iguales
 	
	je true		;Si resultaron iguales, devuelvo true
 	
	mov ecx, longB	;Restauro registros con valores anteriores 
       dec ecx	        ;para seguir buscando
	mov ptrB, edx
	inc ptrB
	mov ptrA, strA
  	
	jmp iter
  	
 
false:	mov eax, 0
	jmp fin
 
true:	mov eax, 1
 	
fin:	;Retorno
	add esp, 4
	pop ebx
	pop edi
	pop esi
	pop ebp
	ret

Codigo C para testear el ASM

#include <stdio.h>
extern int buscar(char*, char*); //Devuelve 1 si encontro la cadena del primer  parametro en el segundo

int main() {

	char a[6] = {'a','a','a','b','c','\0'}; //Tira abc

	char b[14] = {'a','a','d','a','b','a','a','a','a','b','c','d','a','\0'};  //Contiene aaabc
	char c[14] = {'a','a','d','a','b','a','c','b','a','d','c','d','a','\0'};  //No contiene aaabc

	int resT= buscar(a,b);
	int resF= buscar(a,c);

	if (resT == 1) printf("\nOK: Encontro a en b");
	else printf("\nERR: No encontro a en b");

	if (resF == 0) printf("\nOK: No encontro a en c");
	else printf("\nERR: Encontro a en c");

	printf("\n\n");

	return 0;
}

Ejercicio 4

Dados dos strings, generar un tercero que tenga como resultado la intercalación de los dos strings, solo se puede realizar si los strings originales son de la misma long, se debe realizar dicha validación.

Este codigo devuelve como resultado un puntero a char que pide con malloc con el string intercalado por los dos recibidos como parametro, terminando con \0.

Calcula la longitud usando repne scasb contra 0 sobre un ecx negativo que luego convierte a la longitud real.

Usa movsb cambiando constantemente el esi para hacer la intercalacion, en lugar de hacer lodsb de dos registros distintos y stosb al destino.

global intercalar
extern malloc

section .text

%define strA		[ebp+8]
%define strB		[ebp+12]

intercalar:
	;Armo stack frame 
	push ebp
	mov ebp, esp
	push esi
	push edi
	push ebx

	;Calculo long de A y la guardo en ebx
	cld
	xor eax, eax
	mov edi, strA
	mov ecx, -1
	repne scasb
	neg ecx
	sub ecx, 2
	mov ebx, ecx

	;Calculo long de B y la guardo en ecx
	mov edi, strB
	mov ecx, -1
	repne scasb
	neg ecx
	sub ecx, 2

 	;Comparo longitudes
	cmp ebx, ecx
	jne false

	;Si son iguales, calculo cuanto espacio voy a necesitar para el resultado y lo pido
	mov esi, ecx
	shl ebx, 1
 	inc ebx
 	push ebx
 	call malloc
 	add esp, 4
 	
	;Preparo registros
	mov ecx, esi	;ecx= longA = longB
	dec ebx		;ebx= 2*long
	mov edi, eax	;edi apunta al destino
	mov eax, strA	;eax apunta al string A
	mov edx, strB	;edx apunta al string B

	;Intercalo
iter:	mov esi, eax
 	movsb
 	inc eax
	mov esi, edx
	movsb
	inc edx
	loop iter

	;Cierro el string
	xor eax, eax
	stosb
	
	;Calculo q dir tengo q devolver
 	mov eax, edi
	sub eax, ebx
	dec eax
	jmp fin
 
false:	mov eax, 0

fin:	;Retorno
	pop ebx
	pop edi
	pop esi
	pop ebp
	ret 

Este main.c permite testear el codigo asm anterior (libera la memoria que pidio y todo).

#include <stdio.h>
//Retorna el puntero al array de chars que resulta de intercalar los anteriores
//Si no coincidieron las longitudes, devuelve null
extern char* intercalar(char*, char*); 

int main() { 

	char e[5] = {'s','h','r','t','\0'}; 

	char a[7] = {'H','l',' ','u','d','!','\0'}; 
       char b[7] = {'o','a','M','n','o','!','\0'}; 

	char res[13] = {'H','o','l','a',' ','M','u','n','d','o','!','!','\0'};

	char* res1= intercalar(a,b);
	char* res2= intercalar(a,e);

	int i= 0;
	short c= 1;

	if (res1 != 0) {
		printf("OK: Las longitudes de A y B coinciden\n");
		while (i<13) {
			if (i<12) printf("%c", res1[i]);
			c= c && (res1[i] == res[i]);
			i++;
		}
		printf("\n");
		if (c != 0) printf("OK: Intercalo bien\n");
		else printf("ERR: Intercalo mal\n");
	}
	else {
		printf("ERR: Las longitudes de A y B no coinciden\n");
	} 

	if (res2 == 0) printf("OK: Las longitudes de A y E no coinciden\n");
	else printf("ERR: Las longitudes de A y E coinciden\n"); 

	if (res1 !=0) free(res1);

	return 0;
}