Práctica Vectores y Matrices (Organización del Computador II)

De Cuba-Wiki
Saltar a: navegación, buscar
Back.png Volver a la página de la materia

Ejercicio: esSimetrica[editar]

La siguiente funcion dice si una matriz es simetrica respecto de su diagonal principal

global essimetrica

section .text

essimetrica:
; inicio el stack frame
push ebp
mov ebp,esp
push esi
push edi
push ebx


xor ecx, ecx
mov esi, dword [ebp + 8] ; puntero matriz
mov cx, word [ebp + 12] ; tamano

xor ebx, ebx	; ebx <- indice horiz
mov edx,1	; edx <- indice vertical

cicloide:
mov eax, ebx
shl edx,16
mul word cx
shr edx,16

add eax, edx		; eax <- ebx*ancho + edx
mov edi, [esi + eax*4]	; edi <- 1er operando
mov eax, edx

shl edx,16
mul word cx
shr edx,16
add eax, ebx		; eax <- edx*ancho + ebx
cmp edi, [esi + eax*4]
jnz distintas

inc edx			; edx <- edx + 1 (cambio de columna)
cmp edx, ecx		; si ya llegue al final de la fila
jae cambioFila		; cambio de fila

jmp cicloide		; si no, sigo iterando en la misma.


cambioFila:
inc ebx			; ebx <- ebx + 1
lea edx, [ebx +1]	; seteo edx asi para empezar de la diagonal para la derecha
cmp edx, ecx
jge termine
jmp cicloide

termine:
mov eax, 1
jmp fin

distintas:
mov eax, 0


fin:
pop ebx
pop edi
pop esi
pop ebp
ret

y para correrlo desde C...

#include <stdio.h>
extern int essimetrica(unsigned int*, unsigned short n);

int main() {

	unsigned int m1[] = {1,2,3,4,
			     2,1,5,6,
			     3,5,1,7,
			     4,6,7,1};

	unsigned int m2[] = {1,2,3,4,
			     2,1,5,6,
			     3,5,1,7,
			     4,6,9,1};

	int b1 = essimetrica(m1,4);
	int b2 = essimetrica(m2,4);

	printf("%u, %u\n",b1,b2);
	return 0;
}


Ejercicio 20[editar]

Escribir una función que verifique si la suma el elementos de la diagonal principal es igual a la suma de elementos de la diagonal transpuensta (supongo que diagonal "transpuensta" es la antidiagonal).

Este codigo recorre una vez la matriz guardando en edx:eax la suma total de los elementos de la diagonal principal y salvandolos en la stack al terminar, luego hace lo mismo con la antidiagonal, compara y devuelve el resultado.

global diagEq

%define ptrMat	[ebp+8]
%define tamFila	[ebp+12]
%define sumAlta	[ebp-16]
%define sumBaja	[ebp-20]

section .text

diagEq:

;Armo stack frame
	push ebp
	mov ebp, esp
	push ebx
	push esi
	push edi
	sub esp, 8

;Preparo registros
	mov ecx, tamFila	;ecx = iterador
	mov edi, tamFila	;edi = tamaño fila
	mov esi, ptrMat		;esi = puntero a matriz
	xor edx, edx		;edx = parte alta de la suma acumulada
	xor eax, eax		;eax = parte baja de la suma acumulada

;Recorro diagonal principal

diag1:	
	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le sumo a la parte alta
	jl restar1

;sumar1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0x0		;Paso el carry
	jmp seguir1

restar1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0xFFFFFFFF	;Paso el carry y sumo la sign extension

seguir1:
	lea esi, [esi + 4*edi + 4]
	loop diag1

;Guardo acumulados
	mov sumAlta, edx
	mov sumBaja, eax
	

;Repito para anti diagonal

;Preparo registros
	mov ecx, tamFila	;ecx = iterador
	mov esi, ptrMat		;esi = puntero a matriz
	xor edx, edx		;edx = parte alta de la suma acumulada
	xor eax, eax		;eax = parte baja de la suma acumulada

;Recorro antidiagonal 
	lea esi, [esi + 4*edi - 4]
diag2:	
	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le sumo a la parte alta
	jl restar2

;sumar2:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0x0		;Paso el carry
	jmp seguir2

restar2:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0xFFFFFFFF	;Paso el carry y sumo la sign extension

seguir2:
	lea esi, [esi + 4*edi - 4]
	loop diag2

;Comparo
	xor ebx, ebx
	cmp edx, sumAlta
	jne fin
	cmp eax, sumBaja
	jne fin
	mov ebx, 0x1

fin:
	mov eax, ebx

;Retorno
	add esp, 8
	pop edi
	pop esi
	pop ebx
	pop ebp
	ret

Este codigo, en cambio, recorre primero la mitad superior de la matriz y luego la inferior, calculando la diferencia entre las dos diagonales, y luego la compara con cero.

global diagEq

%define ptrMat	[ebp+8]
%define tamFila	[ebp+12]

section .text

diagEq:

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

;Preparo registros
	mov ecx, tamFila	;ecx = iterador
	mov edi, tamFila	;edi = tamaño fila
	mov esi, ptrMat		;esi = puntero a matriz
	xor edx, edx		;edx = parte alta de la suma acumulada
	xor eax, eax		;eax = parte baja de la suma acumulada

;Recorro matriz

diag:	
	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le sumo a la parte alta
	jl restar1

;sumar1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0x0		;Paso el carry
	jmp seguir1
 
restar1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0xFFFFFFFF	;Paso el carry y sumo la sign extension

seguir1:
	dec ecx	
	lea esi, [esi + 4*ecx]	;Apunto esi al elemento de la otra diagonal de la misma fila

	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le resto a la parte alta
	jl restar2

;sumar2:	
	sub eax, ebx		;Resto partes bajas
	sbb edx, 0x0		;Paso el carry
	jmp seguir2

restar2:	
	sub eax, ebx		;Resto partes bajas
	sbb edx, 0xFFFFFFFF	;Paso el carry y resto la sign extension

seguir2:
	dec ecx
	lea esi, [esi + 4*edi]	;Apunto esi al elemento de la diagonal ppal de la proxima fila
	neg ecx
	lea esi, [esi + 4*ecx]
	neg ecx
	jnz diag		;Loopeo mientras no sea cero


;Recorro la mitad inferior de la matriz

	mov ecx, tamFila	;Cargo en ecx de vuelta el tamaño de fila
	mov esi, ptrMat		;Apunto ecx al ultimo elemento
	mov ebx, edi
	imul ebx, edi
	lea esi, [esi + ebx - 1]

diagB:	
	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le sumo a la parte alta
	jl restarB1

;sumarB1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0x0		;Paso el carry
	jmp seguirB1

restarB1:	
	add eax, ebx		;Sumo partes bajas
	adc edx, 0xFFFFFFFF	;Paso el carry y sumo la sign extension

seguirB1:
	dec ecx	
	neg ecx
	lea esi, [esi + 4*ecx]	;Apunto esi al elemento de la otra diagonal de la misma fila
	neg ecx

	mov ebx, [esi]		;ebx = elemento actual
	cmp ebx, 0x0		;Comparo con cero para ver que le resto a la parte alta
	jl restarB2

;sumarB2:	
	sub eax, ebx		;Resto partes bajas
	sbb edx, 0x0		;Paso el carry
	jmp seguirB2

restarB2:	
	sub eax, ebx		;Resto partes bajas
	sbb edx, 0xFFFFFFFF	;Paso el carry y resto la sign extension

seguirB2:
	dec ecx
	neg edi
	lea esi, [esi + 4*edi]	;Apunto esi al elemento de la diagonal ppal de la proxima fila
	neg edi
	lea esi, [esi + 4*ecx]
	jnz diagB		;Loopeo mientras no sea cero


;Comparo
	xor ebx, ebx
	cmp edx, 0
	jne fin
	cmp eax, 0
	jne fin
	mov ebx, 0x1

fin:
	mov eax, ebx

;Retorno
	pop edi
	pop esi
	pop ebx
	pop ebp
 	ret

Este es el codigo C para probar los dos asm anteriores

#include <stdio.h>

//Retorna 1 si true, 0 si false
//Recibe puntero a la matriz y ancho de fila/columna (matriz cuadrada)
extern int diagEq(int* matriz, int n); 

int main() {
	int m[16] = {
		0x7589AC45, 0x87221184, 0xAC449523, 0xFA57CD24,
		0x48792A98, 0xFA57CD24, 0x0F85AAEE, 0x4486AC66,
		0x65AA7854, 0x7589AC45, 0x0F85AAEE, 0xFFA55712,
		0x4578AFDE, 0x2584742A, 0x567CFFA8, 0x4578AFDE	};
	
	int res= diagEq(m, 4);

	if (res==1) printf("Suma de diagonal y antidiagonal iguales.\n");
	else printf("Suma de diagonal y antidiagonal distintas-\n");

	return 0;

}