diff_asm.asm 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. section .data
  14. ; Mascara para realizar un shuffle para repetir los valores del diff
  15. SHUFFLE_MASK: db 2,2,2,255,3,3,3,255,0,0,0,255,1,1,1,255
  16. DIVIDIR: dw 21,21,21,21,0,0,0,0
  17. section .text
  18. ;void diff_asm (
  19. ;unsigned char *src,
  20. ;unsigned char *src2,
  21. ;unsigned char *dst,
  22. ;int filas,
  23. ;int cols)
  24. _diff_asm:
  25. diff_asm:
  26. push rbp
  27. mov rbp, rsp
  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. .loop:
  39. cmp cont, size ; Comparo tamaño con el contador
  40. jge .fin ; Si ya recorri la imagen voy al final
  41. pxor xmm1, xmm1
  42. movdqu xmm0, [src] ; Cargo la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  43. movdqu xmm1, [src2] ; Cargo la imagen 2 => xmm1 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  44. .cuentas: ; Resto componente a componente de 4 pixeles de cada imagen
  45. psubb xmm1, xmm0 ; xmm1 = |B(img1_P1) - R(img2_P1)|G(Img1_P1) - Img2_P2|....|
  46. pabsb xmm0, xmm1 ; Almaceno en xmm0 el valor absoluto de la resta anterior
  47. ; TODO: Arreglar los comentarios por que estan desordenados los pixeles
  48. pxor xmm2, xmm2
  49. movdqu xmm1, xmm0 ; Copio xmm0 a xmm1
  50. punpckhbw xmm0, xmm2 ; Desempaqueto la parte alta => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|R(P2)|A(P2)|
  51. punpcklbw xmm1, xmm2 ; Desempaqueto la parte baja => xmm1 = |B(P3)|G(P3)|R(P3)|A(P3)|B(P4)|G(P4)|R(P4)|A(P4)|
  52. ; Sumo horizontalmente los pixeles:
  53. phaddw xmm0, xmm1 ; xmm0 = |B(P1)+G(P1)|R(P1)+A(P1)|B(P2)+G(P2)|R(P2)+A(P2)|....|
  54. phaddw xmm0, xmm2 ; xmm0 = |B+G+R+A (P1)| B+G+R+A(P2) | B+G+R+A(P3) | B+G+R+A(P4)| 0x0 | 0x0 | 0x0 | 0x0 |
  55. .dividir:
  56. movdqu xmm3, [DIVIDIR] ; Cargo la mascara para dividir
  57. pmullw xmm0, xmm3 ; Multiplico y almaceno parte baja TODO: Demostrar que no puedo llegar a la parte alta
  58. psrlw xmm0, 6 ; Divido por 64
  59. packuswb xmm0, xmm2 ; xmm0 = |P1|P2|P3|P4|0x0|0x0|0x0|0x0|0x0|....|
  60. movdqu xmm2, [SHUFFLE_MASK] ; Cargo la mascara para shuffle
  61. pshufb xmm0, xmm2 ; Le hago un shuffle a xmm0 con los nuevos valores calculados
  62. .write:
  63. movdqu [dst], xmm0 ; Escribo en el destino
  64. .endLoop:
  65. ; TODO: Si el tamaño de la imagen no es multiplo de 4 acá va a sumar y hacer invalid read al llegar al final
  66. add src, PIXEL_SIZE * 4 ; Incremento 4 pixeles
  67. add src2, PIXEL_SIZE * 4
  68. add dst, PIXEL_SIZE * 4
  69. add cont, PIXEL_SIZE * 4
  70. jmp .loop
  71. .fin:
  72. pop rbp
  73. ret