; asmsyntax=nasm default rel global _blur_asm global blur_asm extern convulcion_matrix extern free ; Alias para no volverme loco con los registros %define src rdi %define dst rsi %define cols rdx %define filas r14 %define sigma xmm0 %define radius r8 %define cont_c r9 %define matriz r10 %define filas_faltan r11 %define col_faltan r12 %define basura r13 %define tmp_src rbp ; Algunos defines ultiles %define PIXEL_SIZE 4 ; Mascaras y esas cosas section .data cosa: db 0,4,8,12,255,255,255,255,255,255,255,255,255,255,255,255 section .text ;void blur_asm ( ;unsigned char *src, ;unsigned char *dst, ;int filas, ;int cols, ;float sigma, ;int radius) _blur_asm: blur_asm: push rbp mov rbp, rsp ; Stack frame push r9 push r10 push r11 push r12 push r13 push r14 push r15 .init: mov filas, rcx ;filas push src push dst push cols push filas push radius sub rsp, 16 movdqu [rsp],xmm0 mov rdi, radius call convulcion_matrix mov matriz, rax mov r15, matriz ;copio puntero inicial movdqu xmm0, [rsp] add rsp, 16 pop radius pop filas pop cols pop dst pop src mov r9, rdx ;salvo rdx por los mul mov rax, PIXEL_SIZE mul cols mul radius ; rax:=cols*pix_size*radius => cuantas filas debo saltear add src, rax add dst, rax ; Avanzo "radius" filas (col*pix_size*radius) sub filas, radius ;acomodo filas para ignorar los bordes sub filas, radius ;acomodo filas para ignorar los bordes mov cols, r9 ;recupero cols por el mul sub cols, radius ;resto radius columnas sub cols, radius ;resto radius columnas shl cols, 2 ;multiplico por 4 pixel->byte .iniciarFila: lea src, [src+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde) lea dst, [dst+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde) xor cont_c,cont_c .loop: cmp cols, cont_c ; Comparo tamaƱo con el contador je .finFila ; Si ya recorri la imagen voy al final mov filas_faltan, radius shl filas_faltan, 1 inc filas_faltan ; 2r+1 filas mov tmp_src, src ;salvo para avanzar despues pxor xmm10,xmm10 .loopInterno: ;matriz convulsion mov col_faltan, radius shl col_faltan, 1 inc col_faltan ; 2r+1 columnas shl col_faltan, 2 ; multiplico por 4 para hacer pixel->byte .loopFila: movdqu xmm2, [src] ;levanto 4px cmp col_faltan, 3*PIXEL_SIZE jg .normal ;no quiero shiftear je .tres ;quiero borrar 1 elem ;quiero borrar 3 elem pslldq xmm2, 3*PIXEL_SIZE;ok, borre los que no queria psrldq xmm2, 3*PIXEL_SIZE;ok, borre los que no queria jmp .normal .tres: pslldq xmm2, 1*PIXEL_SIZE ;ok, borre los que no queria psrldq xmm2, 1*PIXEL_SIZE ;ok, borre los que no queria .normal: ;desempaqueto cada pixel a un registro (cada elem como dword) pxor xmm3,xmm3 pxor xmm4,xmm4 pxor xmm5,xmm5 pxor xmm6,xmm6 pxor xmm7,xmm7 pxor xmm8,xmm8 punpcklbw xmm3, xmm2 ;pix a,b punpckhbw xmm4, xmm2 ;pix c,d punpcklwd xmm5, xmm3 ;pix a punpckhwd xmm6, xmm3 ;pix b punpcklwd xmm7, xmm4 ;pix c punpckhwd xmm8, xmm4 ;pix d ;cargo 4 elem de matriz como single movdqu xmm9, [matriz] pshufd xmm11, xmm9, 0x00 ;primer elem en las 4 pos pshufd xmm12, xmm9, 0x55 ;2do... pshufd xmm13, xmm9, 0xAA ;3ro.. pshufd xmm14, xmm9, 0xFF ;4to.. ;acomodo los registros (byte->dword) psrldq xmm5, 3 psrldq xmm6, 3 psrldq xmm7, 3 psrldq xmm8, 3 ;int2float CVTDQ2PS xmm5,xmm5 CVTDQ2PS xmm6,xmm6 CVTDQ2PS xmm7,xmm7 CVTDQ2PS xmm8,xmm8 ;multiplico cada pixel por su coeficiente de la matriz(float) mulps xmm5, xmm11 mulps xmm6, xmm12 mulps xmm7, xmm13 mulps xmm8, xmm14 ;acumulo addps xmm10, xmm5 addps xmm10, xmm6 addps xmm10, xmm7 addps xmm10, xmm8 ;actualizo cuantos faltan sub col_faltan, 4*PIXEL_SIZE add src, PIXEL_SIZE*4 ; Incremento 4 pixeles add matriz, PIXEL_SIZE*4 ; me faltan al menos 4 pixeles en esta fila cmp col_faltan, 0 ;termine jle .finFilaInterna cmp col_faltan, 4*PIXEL_SIZE ;me faltan entre 1 y 3 pixeles, retrocedo suficiente para que me falten 4 exactos jle .retroceder jmp .loopFila .retroceder: mov basura, PIXEL_SIZE*4;cargo 4 pixeles por tanda sub basura, col_faltan ;resto los que me faltan (1-3) sub src, basura ;retrocedo(1-3) para que me falten 4 sub matriz, basura jmp .loopFila .finFilaInterna: dec filas_faltan cmp filas_faltan, 0 je .write jmp .loopInterno .write: CVTPS2DQ xmm10,xmm10 ;me quedan 4 int (dword) <=255, necesito moverlos a 4byte en la parte baja movdqu xmm11, [cosa] ;uso xmm11 de tmp pshufb xmm10, xmm11 ;dejo 0000,0000,0000,rgba movd [dst], xmm10 ; Escribo en el destino .endLoop: mov src, tmp_src ;recupero la posicion a procesar mov matriz, r15 ;voy al inicio de la matriz add src, PIXEL_SIZE ; Incremento 1 pixel add dst, PIXEL_SIZE add cont_c, PIXEL_SIZE jmp .loop .finFila: dec filas cmp filas, qword 0 je .fin lea src, [src+PIXEL_SIZE*radius] ;agrego radius a la columna (termino la fila) lea dst, [dst+PIXEL_SIZE*radius] jmp .iniciarFila .fin: mov rdi, r15 ;inicio de la matriz call free ;libero pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop rbp ret