Advertisement
tievo

Untitled

Nov 17th, 2024
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. section .rodata
  3. ; Acá se pueden poner todas las máscaras y datos que necesiten para el filtro
  4. ALIGN 16
  5. mask128: times 4 dd 128
  6. maskisolate: times 4 dd 0x000000FF
  7. maskalpha: times 4 dd 0xFF000000
  8. all0: times 4 dd 0
  9.  
  10. section .text
  11.  
  12. ; Marca un ejercicio como aún no completado (esto hace que no corran sus tests)
  13. FALSE EQU 0
  14. ; Marca un ejercicio como hecho
  15. TRUE  EQU 1
  16.  
  17. ; Marca el ejercicio 2A como hecho (`true`) o pendiente (`false`).
  18. ;
  19. ; Funciones a implementar:
  20. ;   - ej2a
  21. global EJERCICIO_2A_HECHO
  22. EJERCICIO_2A_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
  23.  
  24. ; Marca el ejercicio 2B como hecho (`true`) o pendiente (`false`).
  25. ;
  26. ; Funciones a implementar:
  27. ;   - ej2b
  28. global EJERCICIO_2B_HECHO
  29. EJERCICIO_2B_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
  30.  
  31. ; Marca el ejercicio 2C (opcional) como hecho (`true`) o pendiente (`false`).
  32. ;
  33. ; Funciones a implementar:
  34. ;   - ej2c
  35. global EJERCICIO_2C_HECHO
  36. EJERCICIO_2C_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
  37.  
  38. ; Dada una imagen origen ajusta su contraste de acuerdo a la parametrización
  39. ; provista.
  40. ;
  41. ; Parámetros:
  42. ;   - dst:    La imagen destino. Es RGBA (8 bits sin signo por canal).
  43. ;   - src:    La imagen origen. Es RGBA (8 bits sin signo por canal).
  44. ;   - width:  El ancho en píxeles de `dst`, `src` y `mask`.
  45. ;   - height: El alto en píxeles de `dst`, `src` y `mask`.
  46. ;   - amount: El nivel de intensidad a aplicar.
  47. global ej2a
  48. ej2a:
  49.     ; Prologo
  50.     push rbp
  51.     mov  rbp, rsp
  52.  
  53.     imul rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
  54.     xor  r9, r9   ; Contador
  55.  
  56.     movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
  57.  
  58.     movd   xmm4, r8d       ; Traigo el parámetro de contraste como dword a xmm4
  59.     pshufd xmm4, xmm4, 0   ; Con el shuffle, hago que xmm4 sea | cont | cont | cont | cont |
  60.  
  61.     .loop:
  62.         call process_contrast ; Llamo a la subrutina que aplica el contraste
  63.         movdqu [rdi], xmm1    ; process_contrast me deja el resultado en xmm1
  64.         add r9, 4             ; Subo el contador por 4 (pixeles)
  65.         cmp r9, rdx           ; Si w*h = r9, ya vimos toda la imagen, y nos vamos.
  66.         je .fin
  67.  
  68.         add rdi, 16  ; 4 pixeles
  69.         add rsi, 16  ; 4 pixeles
  70.         jmp .loop
  71.  
  72.     .fin:
  73.     ; Epilogo
  74.     mov rsp, rbp
  75.     pop rbp
  76.     ret
  77.  
  78.  
  79. process_contrast:
  80.     ; Dentro del cuerpo de esta funcion estoy desalineado (a no ser que se llame desde process_2b o process_2c, pero en ese caso me desalineo en aplicar_contraste_por_canal).
  81.  
  82.     ; Consulté con un profesor y me dijo que no seguir la ABI en este caso no es incorrecto,
  83.     ; debido a que no estoy llamando funciones externas, y las funciones que estoy exportando
  84.     ; empiezan y terminan con la pila alineada a 16.
  85.     ; Esta explicación aplica para todas las funciones internas a las que hago "call" que pueden llegar a desalinear la pila
  86.  
  87.     ; En esta función voy a hacer todo el proceso de aplicar contraste a los 4 pixeles que vengan de rsi, dejar el resultado en XMM1, y el original en XMM0.
  88.     ; La utilizo tanto en 2a, 2b y 2c
  89.  
  90.     movdqu xmm0, [rsi] ; Traigo 4 pixeles del src
  91.  
  92.     ; Manejo el rojo (000000R1 | 000000R2 | 000000R3 | 000000R4)
  93.     movdqu xmm1, xmm0
  94.     pand   xmm1, [maskisolate] ; La mascara de isolate solo me deja el ultimo byte
  95.  
  96.     ; Manejo el verde (000000G1 | 000000G2 | 000000G3 | 000000G4)
  97.     movdqu xmm2, xmm0
  98.     psrld  xmm2, 8  ; Los shifts son para acomodar el azul y el verde donde "iría el rojo"
  99.     pand   xmm2, [maskisolate]
  100.  
  101.     ; Manejo el azul (000000B1 | 000000B2 | 000000B3 | 000000B4)
  102.     movdqu xmm3, xmm0
  103.     psrld  xmm3, 16
  104.     pand   xmm3, [maskisolate]
  105.  
  106.     ; Ahora tengo 0x000000RR | ... en xmm1, lo mismo para blue y green en xmm2 y xmm3
  107.     ; Para cada uno de ellos, llamo a la subrutina aplicar_contraste_por_canal, que me deja en xmm8 el resultado de aplicar contraste a un registro
  108.  
  109.     movdqu xmm8, xmm1
  110.     call   aplicar_contraste_por_canal
  111.     movdqu xmm1, xmm8
  112.  
  113.     movdqu xmm8, xmm2
  114.     call   aplicar_contraste_por_canal
  115.     movdqu xmm2, xmm8
  116.  
  117.     movdqu xmm8, xmm3
  118.     call   aplicar_contraste_por_canal
  119.     movdqu xmm3, xmm8
  120.    
  121.     ; Despues de aplicar contraste, corro los azules y verdes a su posición "original"
  122.     pslld  xmm2, 8
  123.     pslld  xmm3, 16
  124.  
  125.     ; Como los registros son "" disjuntos "" xmm1: (000000RR | ...) xmm2: (0000GG00 | ...) xmm3: (00BB0000 | ...) los junto con un or
  126.     por  xmm1, xmm2
  127.     por  xmm1, xmm3
  128.     por  xmm1, [maskalpha] ; Agrego el alpha con una mascara a FF
  129.  
  130.     ret
  131.  
  132. aplicar_contraste_por_canal:
  133.  
  134.     ; En esta funcion espero que venga en xmm8 un solo canal cada 32 bits (ej 000000RR | 000000RR | .....)
  135.  
  136.     psubd  xmm8, xmm5 ; Restamos 128
  137.  
  138.     pmulld xmm8, xmm4 ; Multiplicamos por el contraste
  139.  
  140.     psrad  xmm8, 5    ; Al hacer un shift aritmetico de 5 bits, divido por 2^5, es decir, 32.
  141.  
  142.     paddd  xmm8, xmm5 ; Sumamos 128
  143.  
  144.     ; Para saturar, vamos a packear con saturacion usando packusdw y packuswb, y despues volver a pmovzxbd para tener 000000CC | ... (CC = Canal)
  145.     packusdw xmm8, xmm8
  146.     packuswb xmm8, xmm8
  147.     pmovzxbd xmm8, xmm8
  148.  
  149.     ret
  150. global ej2b
  151. ej2b:
  152.     ; Prologo
  153.     push rbp
  154.     mov  rbp, rsp
  155.  
  156.     imul   rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
  157.  
  158.     movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
  159.  
  160.     movd   xmm4, r8d       ; Traigo el parámetro de contraste como dword a xmm4
  161.     pshufd xmm4, xmm4, 0   ; Con el shuffle, hago que xmm4 sea | cont | cont | cont | cont |
  162.  
  163.     xor r8, r8 ; Contador (ya cargue el contraste en xmm4)
  164.  
  165.  
  166.     .loop:
  167.         call process_2b     ; Llamo a la subrutina que aplica el contraste condicionalmente
  168.         movdqu [rdi], xmm1  ; Process_2b me deja el resultado en xmm1
  169.         add r8, 4           ; Subo el contador por 4 (pixeles)
  170.         cmp r8, rdx         ; Si w*h = r8, ya vimos toda la imagen
  171.         je .fin
  172.  
  173.         add r9, 4           ; 4 bytes, cada byte me da información para 4 pixeles.
  174.         add rdi, 16         ; 4 pixeles
  175.         add rsi, 16         ; 4 pixeles
  176.         jmp .loop
  177.  
  178.     .fin:
  179.     ;Epilogo
  180.     mov rsp, rbp
  181.     pop rbp
  182.     ret
  183.  
  184. process_2b:
  185.     call process_contrast ; Usando process_contrast, tengo en xmm0 la versión "original" de la imagen, y en xmm1 la versión con contraste
  186.     ; Mi plan de acción consiste en traerme 4 valores de r9, extenderlos con 0 (o no, es lo mismo) a 32 bits, y compararlos con 0
  187.     ; Esto me deja una mascara para andear lo que no deba ser cambiado, invertir la mascara, andear lo contrastado, y hacer un or entre ambas cosas
  188.  
  189.     ; Recordemos que xmm0 y xmm1 estan tomados y son de importancia
  190.  
  191.     movd     xmm2, [r9]
  192.     pmovzxbd xmm2, xmm2   ; Ahora tengo 000000I1 | 000000I2 | ...
  193.  
  194.     pcmpeqd  xmm2, [all0] ; ahora en xmm2 tengo 4 dwords, cada dword es todo 1 si el contraste era 0, o todo 0 si el contraste era ff
  195.  
  196.     pand     xmm0, xmm2   ; en xmm0 tenía el original
  197.  
  198.     pcmpeqd  xmm3, xmm3   ; lleno xmm3 de 1
  199.     pxor     xmm2, xmm3   ; con esto, logro un bitwise-not e invierto mi mascara
  200.  
  201.     pand xmm1, xmm2 ; en xmm1 tenía el contraste aplicado.
  202.  
  203.     ; Ahora, como xmm2 fue invertido logicamente, xmm1 y xmm0 son "disjuntos", entonces puedo hacerles un or
  204.  
  205.     por xmm1, xmm0
  206.  
  207.     ret
  208.    
  209.  
  210.  
  211.  
  212. ; [IMPLEMENTACIÓN OPCIONAL]
  213. ; El enunciado sólo solicita "la idea" de este ejercicio.
  214. ;
  215. ; Dada una imagen origen ajusta su contraste de acuerdo a la parametrización
  216. ; provista.
  217. ;
  218. ; Parámetros:
  219. ;   - dst:     La imagen destino. Es RGBA (8 bits sin signo por canal).
  220. ;   - src:     La imagen origen. Es RGBA (8 bits sin signo por canal).
  221. ;   - width:   El ancho en píxeles de `dst`, `src` y `mask`.
  222. ;   - height:  El alto en píxeles de `dst`, `src` y `mask`.
  223. ;   - control: Una imagen que que regula el nivel de intensidad del filtro en
  224. ;              cada píxel. Es en escala de grises a 8 bits por canal.
  225. global ej2c
  226. ej2c:
  227.     ; Prologo
  228.     push rbp
  229.     mov rbp, rsp
  230.  
  231.     imul rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
  232.     xor r9, r9    ; Contador
  233.  
  234.     movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
  235.  
  236.     .loop:
  237.         call process_2c    ; Llamo a la subrutina que aplica el contraste
  238.         movdqu [rdi], xmm1 ; Process_contrast me deja el resultado en xmm1
  239.         add r9, 4          ; Subo el contador por 4 (pixeles)
  240.         cmp r9, rdx        ; Si w*h = r9, ya vimos toda la imagen
  241.         je .fin
  242.  
  243.         add r8,  4         ; 4 bytes, necesarios para 4 pixeles
  244.         add rdi, 16        ; 4 pixeles
  245.         add rsi, 16        ; 4 pixeles
  246.         jmp .loop
  247.  
  248.     .fin:
  249.     ; Epilogo
  250.     mov rsp, rbp
  251.     pop rbp
  252.     ret
  253.  
  254.  
  255. process_2c:
  256.     ; La idea en esta funcion es simplemente "acomodar" la imagen de control como valores de contraste posibles
  257.     ; para que process_contrast pueda utilizarlos y asi aplicar el contraste dinámicamente
  258.  
  259.     movd     xmm4, [r8]        ; Traigo la "máscara dinamica", de la imagen de control
  260.     pmovzxbd xmm4, xmm4        ; La expando a 0s para tener el mismo formato que en process_contrast
  261.     call     process_contrast  ; Repetimos el proceso de agregar el contraste, pero ahora dinamicamente
  262.     ret
  263.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement