default rel global _blur_asm global blur_asm extern convulcion_matrix ; 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 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 movdqu xmm0, [rsp] add rsp, 16 pop radius pop filas pop cols pop dst pop src ;mov r14,rcx ;guardo rcx para loop 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 mov rax, PIXEL_SIZE mul cols mov cols, rax ;cols:=cols*pix_size .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 add filas_faltan, radius inc filas_faltan ; 2r+1 filas mov tmp_src, src .loopInterno: mov col_faltan, radius add col_faltan, radius inc col_faltan ; 2r+1 columnas mov basura, rdx mov rax,PIXEL_SIZE mul col_faltan ;destruyo rdx mov col_faltan, rax mov rdx, basura ;salvo rdx .loopFila: ;levanto 4px movdqu xmm2, [src] ; Cargo 4 pix de la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......| cmp col_faltan, 3 jg .normal ;no qiuero shiftear je .tres ;quiero borrar 3 elem ;quiero borrar 1 elem .uno: ;shift (4-faltantes) bytes psrldq xmm2, 1;ok, borre los que no queria jmp .normal .tres: psrldq xmm2, 3;ok, borre los que no queria .normal: ;desempaqueto cada pixel a un registro (cada elem como dword) punpcklbw xmm2, xmm3 punpckhbw xmm2, xmm4 punpcklwd xmm3, xmm5 punpckhwd xmm3, xmm6 punpcklwd xmm4, xmm7 punpckhwd xmm4, xmm8 ;cargo 1 elem de matriz como single movd xmm9, [matriz] ;TODO lo clono con mascara a los 4 elem del xmm ;multiplico cada pixel por su coeficiente de la matriz(float) mulps xmm5, xmm9 mulps xmm6, xmm9 mulps xmm7, xmm9 mulps xmm8, xmm9 ;acumulo addps xmm10, xmm5 addps xmm10, xmm6 addps xmm10, xmm7 addps xmm10, xmm8 ;actualizo cuantos faltan sub col_faltan, 4*PIXEL_SIZE cmp col_faltan, 0 jle .finFilaInterna cmp col_faltan, 4 jle .retroceder ;me faltan entre 0 y 4 pixeles, retrocedo suficiente para que me falten 4 exactos add src, PIXEL_SIZE*4 ; Incremento 4 pixeles jmp .loopFila .retroceder: lea src, [src-(4-col_faltan)] jmp .loopFila .finFilaInterna: dec filas_faltan cmp filas_faltan, 0 je .sumar jmp .loopInterno ;avanzo ancho img - (2k+1 pix) ;faltan >0 filas? jmp .loopInterno .sumar: .write: movdqu [dst], xmm10 ; Escribo en el destino .endLoop: mov src, tmp_src 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: pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop rbp ret