diff_asm.asm 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. ; asmsyntax=nasm
  2. default rel
  3. global _diff_asm
  4. global diff_asm
  5. ; Alias para no volverme loco con los registros
  6. %define src rdi
  7. %define src2 rsi
  8. %define dst rdx
  9. %define cont rcx
  10. %define size r8
  11. ; Algunos defines ultiles
  12. %define PIXEL_SIZE 4
  13. %define ALPHA_VALUE 255
  14. %define ALPHA_POS 15
  15. ; Mascaras y esas cosas
  16. section .data
  17. BLUE_MASK: db 0,0,0,ALPHA_POS,4,4,4,ALPHA_POS,8,8,8,ALPHA_POS,12,12,12,ALPHA_POS
  18. GREEN_MASK: db 1,1,1,255,5,5,5,255,9,9,9,255,13,13,13,255
  19. RED_MASK: db 2,2,2,255,6,6,6,255,10,10,10,255,14,14,14,255
  20. section .text
  21. ;void diff_asm (
  22. ;unsigned char *src, unsigned char *src2, unsigned char *dst, int filas, int cols)
  23. _diff_asm:
  24. diff_asm:
  25. push rbp
  26. mov rbp, rsp ; Stack frame
  27. .calc_size: ; Calculo el tamaño de la imagen en bytes
  28. mov r9, dst ; Muevo el destino un rato para hacer el calculo del tamaño de la imagen
  29. mov rax, cont ; Cargo filas
  30. mul size ; Multiplico por las columnas
  31. xor dst, dst ; Limpio temportal
  32. mov dst, PIXEL_SIZE ; Multiplico temporal
  33. mul dst ; Multiplico por el tamaño del pixel
  34. mov size, rax ; Guardo el tamaño
  35. mov dst, r9
  36. xor cont, cont ; Limpio el contador
  37. .pre_loop:
  38. xor rax, rax
  39. mov al, ALPHA_VALUE ; Cargo el valor de alfa
  40. pxor xmm11, xmm11 ; Limpio xmm11
  41. movq xmm11, rax ; Cargo el byte en rax
  42. pslldq xmm11, ALPHA_POS ; Lo muevo en la posición del ultimo alpha
  43. pxor xmm15, xmm15 ; Lo uso como 0 para desempaquetar
  44. movdqu xmm14, [BLUE_MASK] ; Cargo la mascara para sacar el componente azul de cada pixel y calcular el maximo con otros comp
  45. movdqu xmm13, [GREEN_MASK] ; Simil anterior pero con verde
  46. movdqu xmm12, [RED_MASK]
  47. .loop:
  48. cmp cont, size ; Comparo tamaño con el contador
  49. jge .fin ; Si ya recorri la imagen voy al final
  50. pxor xmm1, xmm1
  51. movdqu xmm0, [src] ; Cargo la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  52. movdqu xmm2, [src2] ; Cargo la imagen 2 => xmm1 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  53. .cuentas: ; Resto componente a componente de 4 pixeles de cada imagen
  54. movdqu xmm1, xmm0 ; Copia para desempaquetar la imagen 1
  55. punpcklbw xmm0, xmm15 ; xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|R(P2)|A(P2)|
  56. punpckhbw xmm1, xmm15 ; xmm1 = |B(P3)|G(P3)|R(P3)|A(P3)|B(P4)|G(P5)|R(P5)|A(P5)|
  57. movdqu xmm3, xmm2 ; Copia para desempaquetar la imagen 2
  58. punpcklbw xmm2, xmm15 ; Desempaqueto aprte baja de imagen 2
  59. punpckhbw xmm3, xmm15 ; Parte alta de imagen 2
  60. psubw xmm2, xmm0 ; Resto parte baja de cada imagen
  61. psubw xmm3, xmm1 ; xmm3 = |B(img1_P1) - R(img2_P1)|G(Img1_P1) - Img2_P2|....|
  62. pabsw xmm0, xmm2 ; Calculo el valor absoluto de la resta anterior
  63. pabsw xmm1, xmm3
  64. packuswb xmm0, xmm1 ; Empaqueto los valores de nuevo
  65. .max:
  66. paddb xmm0, xmm11 ; Sumo el canal alpha solitario en xmm0
  67. movdqu xmm2, xmm0 ; Copias para usar los shuffle
  68. movdqu xmm3, xmm0
  69. pshufb xmm0, xmm14 ; Pongo en cada byte de cada pixel el componente azul y el alpha donde corresponde
  70. pshufb xmm2, xmm13 ; Simil anterior, con verde
  71. pshufb xmm3, xmm12 ; Rojo
  72. pmaxub xmm2, xmm3 ; Calculo el mayor de los componentes verde y rojo
  73. pmaxub xmm0, xmm2 ; Calculo el mayor de los componentes de la comparación anterior y azul
  74. .write:
  75. movdqu [dst], xmm0 ; Escribo en el destino
  76. .endLoop:
  77. add src, PIXEL_SIZE * 4 ; Incremento 4 pixeles
  78. add src2, PIXEL_SIZE * 4
  79. add dst, PIXEL_SIZE * 4
  80. add cont, PIXEL_SIZE * 4
  81. jmp .loop
  82. .fin:
  83. pop rbp
  84. ret