Commit 675cfaec authored by Daniel Alejandro Maydana's avatar Daniel Alejandro Maydana
Browse files

agrega C1 2023 otro

parent e451268d
global templosClasicos
global cuantosTemplosClasicos
extern malloc
TAM_STRUCT_TEMPLO equ 24
OFFSET_LARGO equ 0
OFFSET_NOMBRE equ 8
OFFSET_CORTO equ 16
;########### SECCION DE TEXTO (PROGRAMA)
section .text
templosClasicos: ; templosClasicos(templo *temploArr[rdi], size_t temploArr_len[rsi]);
; Prólogo
push rbp
mov rbp, rsp ; Stack alineado a 16bytes
push rbx
push r15
push r14
push r13
push r12
push rdi ; Únicamente para realinear el stack
; Fin prólogo
; Guardo los parámetros en registros no volátiles para que malloc no los altere
mov r15, rdi
mov r14, rsi
call cuantosTemplosClasicos ; Llamo a la funcion para saber el tamaño del nuevo arreglo
; Ahora hago los cálculos para saber cuántos bytes tengo que reservar
mov r8, TAM_STRUCT_TEMPLO
mul r8 ; Hago cuantosTemplosClasicos * TAM_STRUCT_TEMPLO
mov rdi, rax ; Lo paso a rdi para llamar a malloc(cuantosTemplosClasicos * TAM_STRUCT_TEMPLO)
call malloc
mov r12, rax ; Guardo el puntero al nuevo array creado en r12
mov rcx, r14 ; Cargo en rcx la cantidad de iteraciones
mov rdi, r15 ; Vuelvo a poner el puntero al arreglo original en rdi
mov r15, r12 ; Uso r15 para ir agregando al arreglo nuevo
.ciclo:
; Inicializo en 0 cada registro usado
xor r8, r8
xor r9, r9
xor r10, r10
xor rax, rax
; Traigo las partes del struct
mov r8b, [rdi + OFFSET_LARGO] ; M
mov r9, [rdi + OFFSET_NOMBRE] ; char* nombre
mov r10b, [rdi + OFFSET_CORTO] ; N
; Hago W = 2*N+1
mov al, r10b ; Muevo N a al para hacer mul
mov rbx, 2
mul bl ; Hago 2*N
inc ax ; Le sumo 1 al resultado
; Me fijo si W = M
cmp r8w, ax ; Tengo que comparar los 16bits por si hay "overflow" en la multiplicación de 8bits
jne .fin_if
; Como el templo es clásico, lo agrego al arreglo
mov [r15 + OFFSET_LARGO], r8b
mov [r15 + OFFSET_NOMBRE], r9
mov [r15 + OFFSET_CORTO], r10b
; Incremento el puntero del nuevo arreglo para que vaya a la próxima posición
add r15, TAM_STRUCT_TEMPLO
.fin_if:
; Incremento el puntero del arreglo original para que vaya a la próxima posición
add rdi, TAM_STRUCT_TEMPLO
loop .ciclo
; Devuelvo el puntero al inicio del nuevo arreglo
mov rax, r12
; Epílogo
pop rdi
pop r12
pop r13
pop r14
pop r15
pop rbx
pop rbp
ret
cuantosTemplosClasicos: ; cuantosTemplosClasicos_c(templo *temploArr[rdi], size_t temploArr_len[rsi]){
; Prólogo
push rbp
mov rbp, rsp ; Stack alineado a 16bytes
push r15
push r14
push r13
push r12
; Fin prólogo
xor r12, r12 ; Uso r12 como contador
mov rcx, rsi ; Guardo la cantidad de elementos del templo en rcx para usar loop
.ciclo:
; Inicializo en 0 cada registro usado
;xor r15, r15
;xor r14, r14
; Traigo las componentes M y N
mov r15b, [rdi + OFFSET_LARGO] ; M
mov r14b, [rdi + OFFSET_CORTO] ; N
; Hago W = 2*N+1
mov al, r14b ; Muevo N a al para hacer mul
mov r8, 2
mul r8b ; Hago 2*N
inc ax ; Le sumo 1 al resultado
; Me fijo si W = M
cmp r15w, ax ; Tengo que comparar los 16bits por si hay "overflow" en la multiplicación de 8bits
jne .fin_if
inc r12 ; Incremento en 1 la cantidad de templos clásicos
.fin_if:
add rdi, TAM_STRUCT_TEMPLO ; Desfaso TAM_STRUCT_TEMPLO al puntero para que acceda a la siguiente posición
loop .ciclo
; Devuelvo la cantidad de templos clásicos
mov rax, r12
; Epílogo
pop r12
pop r13
pop r14
pop r15
pop rbp
ret
#include "ej1.h"
uint32_t cuantosTemplosClasicos_c(templo *temploArr, size_t temploArr_len){
}
templo* templosClasicos_c(templo *temploArr, size_t temploArr_len){
}
section .data
CONSTANTE_ROJO dd 0.299
CONSTANTE_VERDE dd 0.587
CONSTANTE_AZUL dd 0.114
;########### SECCION DE TEXTO (PROGRAMA)
section .text
global miraQueCoincidencia
miraQueCoincidencia: ; void miraQueCoincidencia_c( uint8_t *A[rdi], uint8_t *B[rsi], uint32_t N[rdx],
; uint8_t *laCoincidencia[rcx] ){
; Prólogo
push rbp
mov rbp, rsp
push rbx
push r12
push r13
push r14
push r15
push rdi ; Únicamente para realinear la pila a 16bytes
; Fin prólogo
mov r15, rcx ; Guardo el puntero a *laCoincidencia para usar loop
mov r14, rdx ; Guardo N
mov r8d, [CONSTANTE_ROJO]
mov r9d, [CONSTANTE_VERDE]
mov r10d, [CONSTANTE_AZUL]
xor r11, r11
; Hago una máscara con las constantes en su correspondiente posición.
; La disposición de cada pixel es bit0 || Azul | Verde | Rojo | Alfa || bit127
pinsrd xmm15, r10d, 0
pinsrd xmm15, r9d, 1
pinsrd xmm15, r8d, 2
pinsrd xmm15, r11d, 3 ; En este insert se ponen 0s en el último Dword para multiplicar el Alfa, así no afecta el resultado de la operación
; -----------------------------------------------------------------------------------
; Si bien los registros xmm permiten traer de a 4 pixeles, solo 1 podrá ser procesado a la vez, ya que hay que hacer operaciones de punto flotante (32bits)
; Por tanto, tengo que convertir cada componente del pixel a float, ocupando todo el espacio del xmm
; Entonces tengo que hacer N*N iteraciones
mov rax, rdx
mul r14 ; Hago N*N
mov rcx, rax
; -----------------------------------------------------------------------------------
.ciclo:
; No utilizo instrucciones SIMD para traer los pixeles a los registros porque se va a procesar de 1 pixel.
; Aun así se podría haber utilizado movdqu pero tendría que haber contemplado los casos borde, que son los tres últimos pixeles
; de las imágenes A y B con algún condicional, sino podría haber un problema de memoria por intentar acceder a una posición que no fue reservada
; para A y B
mov r10, [rdi] ; Traigo un pixel de A
mov r11, [rsi] ; Traigo un pixel de B
movq xmm0, r10 ; Llevo el pixel A a un xmm
movq xmm1, r11 ; Llevo el pixel B a un xmm
; Desempaqueto ambos pixeles para que cada componente tenga 32bits
pmovzxbd xmm0, xmm0
pmovzxbd xmm1, xmm1
pcmpeqd xmm0, xmm1 ; Comparo las componentes de los pixeles
; Si las componentes son iguales, xmm0 = bit0 | 1 | 1 | 1 | 0/1 | bit127
; Los alfa pueden o no ser iguales, hay que tener en cuenta eso para ignorarlo
; Desfaso cada posición de 31bits para quedarme con 0 o 1 en cada posición
psrld xmm0, 31
; Ahora hago dos sumas horizontales para obtener un valor en el primer Dword de xmm0. Teniendo en cuenta que hay que ignorar el alfa,
; si los pixeles son iguales entonces el valor podrá ser 3 o 4 (este último en caso que coincidan los alfa).
; Por tanto, el valor debe ser >= 3
pxor xmm14, xmm14 ; Inicializo xmm14 en 0 para usarlo como segundo parámetro de phadd
phaddd xmm0, xmm14
phaddd xmm0, xmm14
; Ahora extraigo el valor a un registro de próposito general
pextrd r13d, xmm0, 0
; Hago la comparación para saber si son iguales
mov r12, 3
cmp r13, r12
jl .else
; En esta rama se cumple que valor >= 3
; Siendo el caso en que los pixeles son iguales
; Ahora opero con el pixel B (aunque también podría haber sido el A)
; Convierto los enteros a floats
cvtdq2ps xmm1, xmm1
; Multiplico por las constantes correspondientes a cada componente
mulps xmm1, xmm15
; Ahora hago dos sumas horizontales para obtener el valor final, que estará en el primer Dword de xmm1
haddps xmm1, xmm14
haddps xmm1, xmm14
; Convierto el resultado a int32
; Como nota, cabe decir que se usa la versión truncada del convert para que coincida con los test, pero la versión con redondeo parecía dar resultados más precisos
; Aun así, tampoco se especifica en el enunciado de qué manera se tiene que redondear
cvttps2dq xmm1, xmm1
; Extraigo el valor (que está en la primer posición del xmm) y lo pongo en un registro de propósito general
pextrd r13d, xmm1, 0
; Ahora lo mando a la memoria
mov [r15], r13b
jmp .fin_if
.else:
; Si los pixeles son distintos, entonces escribo 255 en la posición de laCoincidencia
mov [r15], BYTE 255
.fin_if:
add r15, 1 ; Incremento el puntero a laCoincidencia en 1 para que vaya al siguiente pixel
; Incremento los punteros de ambas imágenes para acceder a su pixel siguiente (4bytes mide un pixel)
add rdi, 4
add rsi, 4
dec rcx
jnz .ciclo ; No se puede usar loop porque el short jump es muy grande
; Epílogo
pop rdi
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
#include "ej2.h"
void miraQueCoincidencia_c( uint8_t *A, uint8_t *B, uint32_t N,
uint8_t *laCoincidencia ){
}
File added
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment