Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- section .rodata
- ; Acá se pueden poner todas las máscaras y datos que necesiten para el filtro
- ALIGN 16
- mask128: times 4 dd 128
- maskisolate: times 4 dd 0x000000FF
- maskalpha: times 4 dd 0xFF000000
- all0: times 4 dd 0
- section .text
- ; Marca un ejercicio como aún no completado (esto hace que no corran sus tests)
- FALSE EQU 0
- ; Marca un ejercicio como hecho
- TRUE EQU 1
- ; Marca el ejercicio 2A como hecho (`true`) o pendiente (`false`).
- ;
- ; Funciones a implementar:
- ; - ej2a
- global EJERCICIO_2A_HECHO
- EJERCICIO_2A_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
- ; Marca el ejercicio 2B como hecho (`true`) o pendiente (`false`).
- ;
- ; Funciones a implementar:
- ; - ej2b
- global EJERCICIO_2B_HECHO
- EJERCICIO_2B_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
- ; Marca el ejercicio 2C (opcional) como hecho (`true`) o pendiente (`false`).
- ;
- ; Funciones a implementar:
- ; - ej2c
- global EJERCICIO_2C_HECHO
- EJERCICIO_2C_HECHO: db TRUE ; Cambiar por `TRUE` para correr los tests.
- ; Dada una imagen origen ajusta su contraste de acuerdo a la parametrización
- ; provista.
- ;
- ; Parámetros:
- ; - dst: La imagen destino. Es RGBA (8 bits sin signo por canal).
- ; - src: La imagen origen. Es RGBA (8 bits sin signo por canal).
- ; - width: El ancho en píxeles de `dst`, `src` y `mask`.
- ; - height: El alto en píxeles de `dst`, `src` y `mask`.
- ; - amount: El nivel de intensidad a aplicar.
- global ej2a
- ej2a:
- ; Prologo
- push rbp
- mov rbp, rsp
- imul rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
- xor r9, r9 ; Contador
- movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
- movd xmm4, r8d ; Traigo el parámetro de contraste como dword a xmm4
- pshufd xmm4, xmm4, 0 ; Con el shuffle, hago que xmm4 sea | cont | cont | cont | cont |
- .loop:
- call process_contrast ; Llamo a la subrutina que aplica el contraste
- movdqu [rdi], xmm1 ; process_contrast me deja el resultado en xmm1
- add r9, 4 ; Subo el contador por 4 (pixeles)
- cmp r9, rdx ; Si w*h = r9, ya vimos toda la imagen, y nos vamos.
- je .fin
- add rdi, 16 ; 4 pixeles
- add rsi, 16 ; 4 pixeles
- jmp .loop
- .fin:
- ; Epilogo
- mov rsp, rbp
- pop rbp
- ret
- process_contrast:
- ; 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).
- ; Consulté con un profesor y me dijo que no seguir la ABI en este caso no es incorrecto,
- ; debido a que no estoy llamando funciones externas, y las funciones que estoy exportando
- ; empiezan y terminan con la pila alineada a 16.
- ; Esta explicación aplica para todas las funciones internas a las que hago "call" que pueden llegar a desalinear la pila
- ; 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.
- ; La utilizo tanto en 2a, 2b y 2c
- movdqu xmm0, [rsi] ; Traigo 4 pixeles del src
- ; Manejo el rojo (000000R1 | 000000R2 | 000000R3 | 000000R4)
- movdqu xmm1, xmm0
- pand xmm1, [maskisolate] ; La mascara de isolate solo me deja el ultimo byte
- ; Manejo el verde (000000G1 | 000000G2 | 000000G3 | 000000G4)
- movdqu xmm2, xmm0
- psrld xmm2, 8 ; Los shifts son para acomodar el azul y el verde donde "iría el rojo"
- pand xmm2, [maskisolate]
- ; Manejo el azul (000000B1 | 000000B2 | 000000B3 | 000000B4)
- movdqu xmm3, xmm0
- psrld xmm3, 16
- pand xmm3, [maskisolate]
- ; Ahora tengo 0x000000RR | ... en xmm1, lo mismo para blue y green en xmm2 y xmm3
- ; 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
- movdqu xmm8, xmm1
- call aplicar_contraste_por_canal
- movdqu xmm1, xmm8
- movdqu xmm8, xmm2
- call aplicar_contraste_por_canal
- movdqu xmm2, xmm8
- movdqu xmm8, xmm3
- call aplicar_contraste_por_canal
- movdqu xmm3, xmm8
- ; Despues de aplicar contraste, corro los azules y verdes a su posición "original"
- pslld xmm2, 8
- pslld xmm3, 16
- ; Como los registros son "" disjuntos "" xmm1: (000000RR | ...) xmm2: (0000GG00 | ...) xmm3: (00BB0000 | ...) los junto con un or
- por xmm1, xmm2
- por xmm1, xmm3
- por xmm1, [maskalpha] ; Agrego el alpha con una mascara a FF
- ret
- aplicar_contraste_por_canal:
- ; En esta funcion espero que venga en xmm8 un solo canal cada 32 bits (ej 000000RR | 000000RR | .....)
- psubd xmm8, xmm5 ; Restamos 128
- pmulld xmm8, xmm4 ; Multiplicamos por el contraste
- psrad xmm8, 5 ; Al hacer un shift aritmetico de 5 bits, divido por 2^5, es decir, 32.
- paddd xmm8, xmm5 ; Sumamos 128
- ; Para saturar, vamos a packear con saturacion usando packusdw y packuswb, y despues volver a pmovzxbd para tener 000000CC | ... (CC = Canal)
- packusdw xmm8, xmm8
- packuswb xmm8, xmm8
- pmovzxbd xmm8, xmm8
- ret
- global ej2b
- ej2b:
- ; Prologo
- push rbp
- mov rbp, rsp
- imul rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
- movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
- movd xmm4, r8d ; Traigo el parámetro de contraste como dword a xmm4
- pshufd xmm4, xmm4, 0 ; Con el shuffle, hago que xmm4 sea | cont | cont | cont | cont |
- xor r8, r8 ; Contador (ya cargue el contraste en xmm4)
- .loop:
- call process_2b ; Llamo a la subrutina que aplica el contraste condicionalmente
- movdqu [rdi], xmm1 ; Process_2b me deja el resultado en xmm1
- add r8, 4 ; Subo el contador por 4 (pixeles)
- cmp r8, rdx ; Si w*h = r8, ya vimos toda la imagen
- je .fin
- add r9, 4 ; 4 bytes, cada byte me da información para 4 pixeles.
- add rdi, 16 ; 4 pixeles
- add rsi, 16 ; 4 pixeles
- jmp .loop
- .fin:
- ;Epilogo
- mov rsp, rbp
- pop rbp
- ret
- process_2b:
- call process_contrast ; Usando process_contrast, tengo en xmm0 la versión "original" de la imagen, y en xmm1 la versión con contraste
- ; 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
- ; 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
- ; Recordemos que xmm0 y xmm1 estan tomados y son de importancia
- movd xmm2, [r9]
- pmovzxbd xmm2, xmm2 ; Ahora tengo 000000I1 | 000000I2 | ...
- 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
- pand xmm0, xmm2 ; en xmm0 tenía el original
- pcmpeqd xmm3, xmm3 ; lleno xmm3 de 1
- pxor xmm2, xmm3 ; con esto, logro un bitwise-not e invierto mi mascara
- pand xmm1, xmm2 ; en xmm1 tenía el contraste aplicado.
- ; Ahora, como xmm2 fue invertido logicamente, xmm1 y xmm0 son "disjuntos", entonces puedo hacerles un or
- por xmm1, xmm0
- ret
- ; [IMPLEMENTACIÓN OPCIONAL]
- ; El enunciado sólo solicita "la idea" de este ejercicio.
- ;
- ; Dada una imagen origen ajusta su contraste de acuerdo a la parametrización
- ; provista.
- ;
- ; Parámetros:
- ; - dst: La imagen destino. Es RGBA (8 bits sin signo por canal).
- ; - src: La imagen origen. Es RGBA (8 bits sin signo por canal).
- ; - width: El ancho en píxeles de `dst`, `src` y `mask`.
- ; - height: El alto en píxeles de `dst`, `src` y `mask`.
- ; - control: Una imagen que que regula el nivel de intensidad del filtro en
- ; cada píxel. Es en escala de grises a 8 bits por canal.
- global ej2c
- ej2c:
- ; Prologo
- push rbp
- mov rbp, rsp
- imul rdx, rcx ; Multiplico width por height para tener la cantidad de iteraciones
- xor r9, r9 ; Contador
- movdqu xmm5, [mask128] ; Muevo la mascara para sumar y restar 128
- .loop:
- call process_2c ; Llamo a la subrutina que aplica el contraste
- movdqu [rdi], xmm1 ; Process_contrast me deja el resultado en xmm1
- add r9, 4 ; Subo el contador por 4 (pixeles)
- cmp r9, rdx ; Si w*h = r9, ya vimos toda la imagen
- je .fin
- add r8, 4 ; 4 bytes, necesarios para 4 pixeles
- add rdi, 16 ; 4 pixeles
- add rsi, 16 ; 4 pixeles
- jmp .loop
- .fin:
- ; Epilogo
- mov rsp, rbp
- pop rbp
- ret
- process_2c:
- ; La idea en esta funcion es simplemente "acomodar" la imagen de control como valores de contraste posibles
- ; para que process_contrast pueda utilizarlos y asi aplicar el contraste dinámicamente
- movd xmm4, [r8] ; Traigo la "máscara dinamica", de la imagen de control
- pmovzxbd xmm4, xmm4 ; La expando a 0s para tener el mismo formato que en process_contrast
- call process_contrast ; Repetimos el proceso de agregar el contraste, pero ahora dinamicamente
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement