Práctica Strings (Organización del Computador II)
Ejercicio 1
Dado un string, armar una rutina que calcule la longitud.
- 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.
- Generar una rutina que permita comprobar si en un string determinado, se encuentra incluida
- un carácter
- una palabra
- 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; }