Parcourir la source

Algunas mejoras en los comentarios para explicar como funciona y aumenté la presición.

Fabian il y a 11 ans
Parent
commit
d50d8ccd84
1 fichiers modifiés avec 28 ajouts et 27 suppressions
  1. 28 27
      filtros/diff_asm.asm

+ 28 - 27
filtros/diff_asm.asm

@@ -12,25 +12,27 @@ global diff_asm
 %define size r8
 
 ; Algunos defines ultiles
-%define PIXEL_SIZE	4
-
+%define PIXEL_SIZE  4
+%define SHIFT_VALUE 8                   ; Potencia de 2 para hacer el calculo del promedio en enteros.
+%define DIV_VALUE   (2^SHIFT_VALUE)/3   ; Multiplico por el valor sobre 3 para hacer un shift de 8bits a la derecha. (DIV * P)>>8
+                                        ; TODO: El valor SHIFT_VALUE NO PUEDE ser mayor a 8 o pierdo información en la multiplicacion
+                                        ; Para ser mayor tengo que multiplicar y tener en cuenta la parte alta (pmulhw)
+                                        ; Se que el valor máximo que va a haber que multiplicar es es (255*3), por eso puedo
+                                        ; multiplicar hasta por 85 = (256/3), sin que supere 2^16, quedando en parte baja para pmullw.
+
+; Mascaras y esas cosas
 section .data
-    ; Mascara para realizar un shuffle para repetir los valores del diff
-	SHUFFLE_MASK: db 2,2,2,255,3,3,3,255,0,0,0,255,1,1,1,255
-	DIVIDIR: dw 21,21,21,21,0,0,0,0
+    SHUFFLE_MASK: db 2,2,2,255,3,3,3,255,0,0,0,255,1,1,1,255    ; Mascara para realizar un shuffle para repetir los valores del diff
+    DIVIDIR: dw DIV_VALUE,DIV_VALUE,DIV_VALUE,DIV_VALUE,0,0,0,0 ; Mascara para dividir con enteros usando shifts
 
 section .text
 ;void diff_asm    (
-	;unsigned char *src,
-    ;unsigned char *src2,
-	;unsigned char *dst,
-	;int filas,
-	;int cols)
+    ;unsigned char *src, unsigned char *src2, unsigned char *dst, int filas, int cols)
 
 _diff_asm:
 diff_asm:
     push rbp
-    mov rbp, rsp
+    mov rbp, rsp                ; Stack frame
 
 .calc_size:                     ; Calculo el tamaño de la imagen en bytes
     mov r9, dst                 ; Muevo el destino un rato para hacer el calculo del tamaño de la imagen
@@ -41,8 +43,8 @@ diff_asm:
     mul dst                     ; Multiplico por el tamaño del pixel
     mov size, rax               ; Guardo el tamaño
     mov dst, r9
-
     xor cont, cont              ; Limpio el contador
+    movdqu xmm3, [DIVIDIR]      ; Cargo el valor para las divisiones para el promedio
 
 .loop:
     cmp cont, size              ; Comparo tamaño con el contador
@@ -53,32 +55,31 @@ diff_asm:
 
 .cuentas:                       ; Resto componente a componente de 4 pixeles de cada imagen
     psubb xmm1, xmm0            ; xmm1 = |B(img1_P1) - R(img2_P1)|G(Img1_P1) - Img2_P2|....|
-	pabsb xmm0, xmm1            ; Almaceno en xmm0 el valor absoluto de la resta anterior
+    pabsb xmm0, xmm1            ; Almaceno en xmm0 el valor absoluto de la resta anterior
 
     ; TODO: Arreglar los comentarios por que estan desordenados los pixeles
-	pxor xmm2, xmm2
-	movdqu xmm1, xmm0           ; Copio xmm0 a xmm1
-	punpckhbw xmm0, xmm2        ; Desempaqueto la parte alta => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|R(P2)|A(P2)|
-	punpcklbw xmm1, xmm2        ; Desempaqueto la parte baja => xmm1 = |B(P3)|G(P3)|R(P3)|A(P3)|B(P4)|G(P4)|R(P4)|A(P4)|
+    pxor xmm2, xmm2
+    movdqu xmm1, xmm0           ; Copio xmm0 a xmm1
+    punpckhbw xmm0, xmm2        ; Desempaqueto la parte alta => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|R(P2)|A(P2)|
+    punpcklbw xmm1, xmm2        ; Desempaqueto la parte baja => xmm1 = |B(P3)|G(P3)|R(P3)|A(P3)|B(P4)|G(P4)|R(P4)|A(P4)|
 
-								; Sumo horizontalmente los pixeles:
-	phaddw xmm0, xmm1           ; xmm0 = |B(P1)+G(P1)|R(P1)+A(P1)|B(P2)+G(P2)|R(P2)+A(P2)|....|
-	phaddw xmm0, xmm2           ; xmm0 = |B+G+R+A (P1)| B+G+R+A(P2) | B+G+R+A(P3) | B+G+R+A(P4)| 0x0 | 0x0 | 0x0 | 0x0 |
+                                ; Sumo horizontalmente los pixeles:
+    phaddw xmm0, xmm1           ; xmm0 = |B(P1)+G(P1)|R(P1)+A(P1)|B(P2)+G(P2)|R(P2)+A(P2)|....|
+    phaddw xmm0, xmm2           ; xmm0 = |B+G+R+A (P1)| B+G+R+A(P2) | B+G+R+A(P3) | B+G+R+A(P4)| 0x0 | 0x0 | 0x0 | 0x0 |
 
 .dividir:
-	movdqu xmm3, [DIVIDIR]		; Cargo la mascara para dividir
-	pmullw xmm0, xmm3			; Multiplico y almaceno parte baja TODO: Demostrar que no puedo llegar a la parte alta
-	psrlw xmm0, 6				; Divido por 64
+    pmullw xmm0, xmm3           ; Multiplico y almaceno parte baja, no llego a usar la parte alta si SHIFT_VALUE < 8
+    psrlw xmm0, SHIFT_VALUE     ; Divido por el valor
 
-	packuswb xmm0, xmm2         ; xmm0 = |P1|P2|P3|P4|0x0|0x0|0x0|0x0|0x0|....|
+    packuswb xmm0, xmm2         ; xmm0 = |P1|P2|P3|P4|0x0|0x0|0x0|0x0|0x0|....|
 
-	movdqu xmm2, [SHUFFLE_MASK] ; Cargo la mascara para shuffle
-	pshufb xmm0, xmm2           ; Le hago un shuffle a xmm0 con los nuevos valores calculados
+    movdqu xmm2, [SHUFFLE_MASK] ; Cargo la mascara para shuffle
+    pshufb xmm0, xmm2           ; Le hago un shuffle a xmm0 con los nuevos valores calculados
 .write:
     movdqu [dst], xmm0          ; Escribo en el destino
 .endLoop:
     ; TODO: Si el tamaño de la imagen no es multiplo de 4 acá va a sumar y hacer invalid read al llegar al final
-    add src, PIXEL_SIZE	* 4     ; Incremento 4 pixeles
+    add src, PIXEL_SIZE * 4     ; Incremento 4 pixeles
     add src2, PIXEL_SIZE * 4
     add dst, PIXEL_SIZE * 4
     add cont, PIXEL_SIZE * 4