Diferencia entre revisiones de «Práctica Vectores y Matrices (Organización del Computador II)»
De Cuba-Wiki
(Sin diferencias)
|
Revisión del 03:42 10 oct 2006
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; }