; asmsyntax=nasm default rel global _diff_asm global diff_asm ; Alias para no volverme loco con los registros %define src rdi %define src2 rsi %define dst rdx %define cont rcx %define size r8 ; Algunos defines ultiles %define PIXEL_SIZE 4 %define ALPHA_VALUE 255 %define ALPHA_POS 15 ; Mascaras y esas cosas section .data BLUE_MASK: db 0,0,0,ALPHA_POS,4,4,4,ALPHA_POS,8,8,8,ALPHA_POS,12,12,12,ALPHA_POS GREEN_MASK: db 1,1,1,255,5,5,5,255,9,9,9,255,13,13,13,255 RED_MASK: db 2,2,2,255,6,6,6,255,10,10,10,255,14,14,14,255 section .text ;void diff_asm ( ;unsigned char *src, unsigned char *src2, unsigned char *dst, int filas, int cols) _diff_asm: diff_asm: push rbp 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 mov rax, cont ; Cargo filas mul size ; Multiplico por las columnas xor dst, dst ; Limpio temportal mov dst, PIXEL_SIZE ; Multiplico temporal 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 .pre_loop: xor rax, rax mov al, ALPHA_VALUE ; Cargo el valor de alfa pxor xmm11, xmm11 ; Limpio xmm11 movq xmm11, rax ; Cargo el byte en rax pslldq xmm11, ALPHA_POS ; Lo muevo en la posición del ultimo alpha pxor xmm15, xmm15 ; Lo uso como 0 para desempaquetar movdqu xmm14, [BLUE_MASK] ; Cargo la mascara para sacar el componente azul de cada pixel y calcular el maximo con otros comp movdqu xmm13, [GREEN_MASK] ; Simil anterior pero con verde movdqu xmm12, [RED_MASK] .loop: cmp cont, size ; Comparo tamaño con el contador jge .fin ; Si ya recorri la imagen voy al final pxor xmm1, xmm1 movdqu xmm0, [src] ; Cargo la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......| movdqu xmm2, [src2] ; Cargo la imagen 2 => xmm1 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......| .cuentas: ; Resto componente a componente de 4 pixeles de cada imagen movdqu xmm1, xmm0 ; Copia para desempaquetar la imagen 1 punpcklbw xmm0, xmm15 ; xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|R(P2)|A(P2)| punpckhbw xmm1, xmm15 ; xmm1 = |B(P3)|G(P3)|R(P3)|A(P3)|B(P4)|G(P5)|R(P5)|A(P5)| movdqu xmm3, xmm2 ; Copia para desempaquetar la imagen 2 punpcklbw xmm2, xmm15 ; Desempaqueto aprte baja de imagen 2 punpckhbw xmm3, xmm15 ; Parte alta de imagen 2 psubw xmm2, xmm0 ; Resto parte baja de cada imagen psubw xmm3, xmm1 ; xmm3 = |B(img1_P1) - R(img2_P1)|G(Img1_P1) - Img2_P2|....| pabsw xmm0, xmm2 ; Calculo el valor absoluto de la resta anterior pabsw xmm1, xmm3 packuswb xmm0, xmm1 ; Empaqueto los valores de nuevo .max: paddb xmm0, xmm11 ; Sumo el canal alpha solitario en xmm0 movdqu xmm2, xmm0 ; Copias para usar los shuffle movdqu xmm3, xmm0 pshufb xmm0, xmm14 ; Pongo en cada byte de cada pixel el componente azul y el alpha donde corresponde pshufb xmm2, xmm13 ; Simil anterior, con verde pshufb xmm3, xmm12 ; Rojo pmaxub xmm2, xmm3 ; Calculo el mayor de los componentes verde y rojo pmaxub xmm0, xmm2 ; Calculo el mayor de los componentes de la comparación anterior y azul .write: movdqu [dst], xmm0 ; Escribo en el destino .endLoop: add src, PIXEL_SIZE * 4 ; Incremento 4 pixeles add src2, PIXEL_SIZE * 4 add dst, PIXEL_SIZE * 4 add cont, PIXEL_SIZE * 4 jmp .loop .fin: pop rbp ret