Práctica Vectores y Matrices (Organización del Computador II)
Ejercicio: esSimetrica
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
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; }