diff_asm.asm 3.7 KB

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