Commit 8b76ee33 authored by Andres Galeota's avatar Andres Galeota
Browse files

Segundo parcial

parents
File added
br ej1.asm:157
run
info register r11
run
step
info register r11
q
CC=c99
CFLAGS= -Wall -Wextra -pedantic -O0 -g -lm -Wno-unused-variable -Wno-unused-parameter -no-pie -z noexecstack
NASM=nasm
NASMFLAGS=-f elf64 -g -F DWARF
all: main tester
OBJS := ej1_c.o ej1_asm.o
tester: tester.c $(OBJS)
$(CC) $(CFLAGS) $^ -o $@
main: main.c $(OBJS)
$(CC) $(CFLAGS) $^ -o $@
ej1_c.o: ej1.c ej1.h
$(CC) $(CFLAGS) -c $< -o $@
ej1_asm.o: ej1.asm ej1.h
$(NASM) $(NASMFLAGS) $< -o $@
clean:
rm -f *.o
rm -f main tester
rm -f salida.caso.*
; /** defines bool y puntero **/
%define NULL 0
%define TRUE 1
%define FALSE 0
section .data
%define OFFSET_FIRST 0
%define OFFSET_LAST 8
%define OFFSET_NEXT 0
%define OFFSET_PREVIOUS 8
%define OFFSET_TYPE 16
%define OFFSET_HASH 24
section .text
global string_proc_list_create_asm
global string_proc_node_create_asm
global string_proc_list_add_node_asm
global string_proc_list_concat_asm
; FUNCIONES auxiliares que pueden llegar a necesitar:
extern calloc
extern malloc
extern free
extern str_concat
; Signatura de la función:
; string_proc_list* string_proc_list_create_asm(void);
; Inicializa una estructura de lista.
; Mapeo de parámetros a registros:
; La función no recibe ninguún parámetro
; Idea de la implementación:
; Tengo que pedir memoria para la estructura, que ocupa 16 bytes, pues son dos punteros
string_proc_list_create_asm:
; prólogo
push rbp
mov rbp, rsp
; cuerpo
; Quiero llamar a calloc(numElems = 1, sizeElems = 16)
; cargo los parámetros:
mov rdi, 1
mov rsi, 16
call calloc
; ahora tengo un rax el puntero a la posición de memoria reservada
; uso calloc que ya me pone todo en cero, pues quiero que sean punteros nulos
; como ya tengo en rax el puntero que tengo que devolver, no tengo que hacer más nada :)
; epílogo
pop rbp
ret
; Signatura de la función:
; string_proc_node* string_proc_node_create_asm(uint8_t type, char* hash);
; Mapeo de parámetros a registros:
; rdi[type], rsi[hash]
; Idea de la implementación:
; Tengo que crear el nodo, para esto tengo que reservar 32 bytes de memoria,
; una vez creado el nodo inicializo los campos, type, hash. El campo next lo inicializo como nulo, pues es el último nodo
; y el camplo previous también como null, pues es el primer nodo
string_proc_node_create_asm:
; prólogo
push rbp
mov rbp, rsp
push r12
push r13
push r14
push r15
; cuerpo
; Primero me guardo los parámetros en registros no volátiles para no perderlos al llamar a calloc
xor r15, r15 ; limpio r15
xor r14, r14 ; limpio r14
mov r15, rdi ; r15 = type
mov r14, rsi ; r14 = hash
; Ahora quiero llamar calloc(numElems = 1, sizeElems = 32);
; cargo los parámetros:
mov rdi, 1
mov rsi, 32
call calloc
; ahora tengo en rax el puntero al nodo
; Inicializo los campos type y hash:
mov byte [rax + OFFSET_TYPE], r15b
mov qword [rax + OFFSET_HASH], r14
; los punteros next y previous del nodo está inicalizados como nulos, pues use calloc
; como ya tengo en rax el puntero que quiero devolver, no tengo que hacer nada más
; epílogo
pop r15
pop r14
pop r13
pop r12
pop rbp
ret
; Signatura de la función:
; void string_proc_list_add_node_asm(string_proc_list* list, uint8_t type, char* hash)
; Mapeo de parámetros a registros:
; rdi[list], rsi[type], rdx[hash]
; Idea de la implementación:
; Puedo llamar a la función string_proc_node* string_proc_node_create_asm(uint8_t type, char* hash);
; para crear un nodo con el type y el hash pasados como parámetro, next debe quedarse como un puntero nulo, pues es el último nodo,
; y previous debe apuntar al último nodo de la lista
; luego tengo que ir al último nodo de la lista y setear el campo next como el puntero al nodo recién creado
; por último hacer list.last = puntero al nodo creado
string_proc_list_add_node_asm:
; prólogo
push rbp
mov rbp, rsp
push r12
push r13
push r14
push r15
; cuerpo
; Primero me guardo los parámetros originales en registros no volátiles para que no se pierdan al realizar llamados a funciones
; limpio los no volátiles y rax:
xor r15, r15
xor r14, r14
xor r13, r13
xor r12, r12
xor rax, rax
mov r15, rdi ; r15 = list
mov r14, rsi ; r14 = type
mov r13, rdx ; r13 = hash
; Quiero llamar a la función: string_proc_node* string_proc_node_create_asm(uint8_t type, char* hash);
; cargo los parámetros:
mov rdi, r14 ; rdi = type
mov rsi, r13 ; rsi = hash
call string_proc_node_create_asm
; ahora tengo en rax el puntero al nodo creado, con los campos type y hash ya inicializados con el valor correspondiente
; me lo guardo en un registro no volátil
mov r12, rax ; r12 = nodo*
; Tengo que inicializar el campo previous con el puntero al último nodo de la lista pasada por parámetro, osea nodo.previous = list.last
mov r11, qword [r15 + OFFSET_LAST] ; r11 = list.last
; ahora tengo en r11 el puntero last, chequeo si la lista no es vacía
cmp r11, 0
je .lista_vacia
; si la lista no es vacía:
; tengo que ir al último nodo de la lista y setear el campo next como el puntero al nodo recién creado
; En r11 tengo el puntero al último nodo de la lista Y en r12 el puntero al nodo creado
mov qword [r11 + OFFSET_NEXT], r12
jmp .lista_no_vacia
.lista_vacia:
mov qword [r15 + OFFSET_FIRST], r12
.lista_no_vacia:
; por último hacer list.last = puntero al nodo creado
; en r15 tengo list
mov qword [r12 + OFFSET_PREVIOUS], r11 ; nodo.previous = list.last
mov qword [r15 + OFFSET_LAST], r12
; epílogo
pop r15
pop r14
pop r13
pop r12
pop rbp
ret
; Signatura de la función:
; char* string_proc_list_concat_asm(string_proc_list* list, uint8_t type, char* hash);
; Genera un nuevo hash concatenando el pasado por parámetro con todos los hashes de los nodos
; de la lista cuyos tipos coinciden con el pasado por parámetro.
; Mapeo de parámetros a registros:
; rdi[list], rsi[type], rdx[hash]
; Idea de la implementación:
; Lo que tengo que hacer es ir recorriendo los nodos, me traigo el valor de type, comparo con el valor pasado por parámetro
; Si los type coinciden, concateno los strings
; Si los type NO COINCIDEN, paso al siguiente nodo
;
string_proc_list_concat_asm:
; prólogo
push rbp
mov rbp, rsp
push r12
push r13
push r14
push r15
push rbx
sub rsp, 8
; cuerpo
; Primero me guardo los parámetros originales de la función en registros no volátiles, para no perderlos al hacer llamadas a funciones:
xor r15, r15
xor r14, r14
xor r13, r13
xor r12, r12
xor rbx, rbx
mov r15, rdi ; r15 = list
mov r14, rsi ; r14 = type
mov r13, rdx ; r13 = hash
;mov rbx, r13 ; rbx = hash // esta copia me la hago para poder comprar después y saber si esto ó no en la primera iteración
; si no estoy en la primera iteración, quiero hacer free con el puntero que estaba guardado en r13
mov r12, [r15 + OFFSET_FIRST] ; r12 = list->first
; chequeo si el puntero es nulo:
cmp r12, 0
je .fin
.bucle:
mov r11b, byte [r12 + OFFSET_TYPE] ; r11b = nodo.type
cmp r14b, r11b ; comparo el type del nodo con el ṕasado por parámetro
jne .avanzar_nodo
; En el caso de que el type coincida quiero concatenar los hashs
mov r10, [r12 + OFFSET_HASH] ; r10 = nodo.hash
; quiero llamar a la función: char* str_concat(char* a, char* b);
; cargo los parámetros:
mov rdi, r13 ; rdi = hash (en la primera iteración), luego la concatenación de hashes
mov rsi, r10 ; rsi = nodo.hash
call str_concat
; Ahora tengo en rax el puntero al hash creado al concatenar ambos
; me lo guardo en un registro no volátil:
; Si es la primera iteración, en r13 tengo el hash pasado por parámetro, así que no necesito hacer free
;mov r13, rax
;cmp r13, rbx
;je .no_hacer_free
;cmp r12, [r15]
;je .no_hacer_free
;.hacer_free:
; mov rbx, rax ;
; Si los punteros no son iguales, quiere decir que no estoy en la primera iteración, y necesito hacer free:
; quiero llamar la función: void free(void *ptr)
; cargo el parámetro
; mov rdi, r13
; call free
;.no_hacer_free:
mov r13, rax
;mov r13, rbx
; Como cada vez que itere voy a llamar a str_concat y este me va a concatenar los parámetros creando uno nuevo,
; necesito liberar la memoria
.avanzar_nodo:
mov r12, [r12 + OFFSET_NEXT] ; me guardo el puntero al siguiente nodo en r12
; chequeo si el puntero es nulo:
cmp r12, 0
je .fin
jmp .bucle
.fin:
mov r13, rax
; epílogo
add rsp, 8
pop rbx
pop r15
pop r14
pop r13
pop r12
pop rbp
ret
#include "ej1.h"
string_proc_list* string_proc_list_create(void){
}
string_proc_node* string_proc_node_create(uint8_t type, char* hash){
}
void string_proc_list_add_node(string_proc_list* list, uint8_t type, char* hash){
}
char* string_proc_list_concat(string_proc_list* list, uint8_t type , char* hash){
}
/** AUX FUNCTIONS **/
void string_proc_list_destroy(string_proc_list* list){
/* borro los nodos: */
string_proc_node* current_node = list->first;
string_proc_node* next_node = NULL;
while(current_node != NULL){
next_node = current_node->next;
string_proc_node_destroy(current_node);
current_node = next_node;
}
/*borro la lista:*/
list->first = NULL;
list->last = NULL;
free(list);
}
void string_proc_node_destroy(string_proc_node* node){
node->next = NULL;
node->previous = NULL;
node->hash = NULL;
node->type = 0;
free(node);
}
char* str_concat(char* a, char* b) {
int len1 = strlen(a);
int len2 = strlen(b);
int totalLength = len1 + len2;
char *result = (char *)malloc(totalLength + 1);
strcpy(result, a);
strcat(result, b);
return result;
}
void string_proc_list_print(string_proc_list* list, FILE* file){
uint32_t length = 0;
string_proc_node* current_node = list->first;
while(current_node != NULL){
length++;
current_node = current_node->next;
}
fprintf( file, "List length: %d\n", length );
current_node = list->first;
while(current_node != NULL){
fprintf(file, "\tnode hash: %s | type: %d\n", current_node->hash, current_node->type);
current_node = current_node->next;
}
}
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#define USE_ASM_IMPL 1
/** Lista **/
typedef struct string_proc_list_t {
struct string_proc_node_t* first;
struct string_proc_node_t* last;
} string_proc_list;
/** Nodo **/
typedef struct string_proc_node_t {
struct string_proc_node_t* next;
struct string_proc_node_t* previous;
uint8_t type;
char* hash;
} string_proc_node;
/** Funciones a implementar: **/
string_proc_list* string_proc_list_create(void);
string_proc_list* string_proc_list_create_asm(void);
string_proc_node* string_proc_node_create(uint8_t type, char* hash);
string_proc_node* string_proc_node_create_asm(uint8_t type, char* hash);
void string_proc_list_add_node(string_proc_list* list, uint8_t type, char* hash);
void string_proc_list_add_node_asm(string_proc_list* list, uint8_t type, char* hash);
char* string_proc_list_concat(string_proc_list* list, uint8_t type, char* hash);
char* string_proc_list_concat_asm(string_proc_list* list, uint8_t type, char* hash);
/** Funciones Auxiliares:**/
/**
* Libera la memoria de la lista y sus nodos.
*/
void string_proc_list_destroy(string_proc_list* list);
/**
* Libera la memoria del nodo.
*/
void string_proc_node_destroy(string_proc_node* node);
/**
* Concatena dos strings a y b.
* Retorna el resultado en uno nuevo, creado via malloc.
*/
char* str_concat(char* a, char* b);
/**
* Imprime la lista list en el archivo file.
*/
void string_proc_list_print(string_proc_list* list, FILE* file);
File added
File added
File added
#include "ej1.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
/**
* crea y destruye a una lista vacía
*/
void test_create_destroy_list(){
string_proc_list * list = string_proc_list_create_asm();
string_proc_list_destroy(list);
}
/**
* crea y destruye un nodo
*/
void test_create_destroy_node(){
string_proc_node* node = string_proc_node_create_asm(0, "hash");
string_proc_node_destroy(node);
}
/**
* crea una lista y le agrega nodos
*/
void test_create_list_add_nodes()
{
string_proc_list * list = string_proc_list_create_asm();
string_proc_list_add_node_asm(list, 0, "hola");
string_proc_list_add_node_asm(list, 0, "a");
string_proc_list_add_node_asm(list, 0, "todos!");
string_proc_list_destroy(list);
}
/**
* crea una lista y le agrega nodos. Luego aplica la lista a un hash.
*/
void test_list_concat()
{
string_proc_list * list = string_proc_list_create();
string_proc_list_add_node(list, 0, "hola");
string_proc_list_add_node(list, 0, "a");
string_proc_list_add_node(list, 0, "todos!");
char* new_hash = string_proc_list_concat(list, 0, "hash");
string_proc_list_destroy(list);
free(new_hash);
}
/**
* Corre los test a se escritos por lxs alumnxs
*/
void run_tests(){
/* Aqui pueden comenzar a probar su codigo */
test_create_destroy_list();
test_create_destroy_node();
test_create_list_add_nodes();
test_list_concat();
}
int main (void){
run_tests();
return 0;
}
#!/usr/bin/env bash
reset
command -v valgrind > /dev/null
if [ $? -ne 0 ]; then
echo "ERROR: No se encuentra valgrind."
exit 1
fi
make main
if [ $? -ne 0 ]; then
echo "ERROR: Error de compilacion."
exit 1
fi
valgrind --show-reachable=yes --leak-check=full --error-exitcode=1 ./main
if [ $? -ne 0 ]; then
echo " **Error de memoria"
exit 1
fi
\ No newline at end of file
#!/usr/bin/env bash
reset
echo " "
echo "**Compilando"
make tester
if [ $? -ne 0 ]; then
echo " **Error de compilacion"
exit 1
fi
echo " "
echo "**Corriendo diferencias con la catedra"
DIFFER="diff -d"
ERRORDIFF=0
./tester
$DIFFER salida.caso.propio.ej1.txt salida.catedra.ej1.txt > /tmp/diff1
if [ $? -ne 0 ]; then
echo " **Discrepancia en el ejercicio 1"
ERRORDIFF=1
fi
echo " "
if [ $ERRORDIFF -eq 0 ]; then
echo "**Todos los tests pasan"
fi
echo " "
command -v valgrind > /dev/null
if [ $? -ne 0 ]; then
echo "ERROR: No se encuentra valgrind."
exit 1
fi
valgrind --show-reachable=yes --leak-check=full --error-exitcode=1 ./tester
if [ $? -ne 0 ]; then
echo " **Error de memoria"
exit 1
fi
\ No newline at end of file
== Ejercicio 1a ==
Creando lista vacia
======================== Libera memoria =======================
Creando nodo vacio
======================== Libera memoria =======================
Creando lista vacia
List length: 0
Agregando estrellas:
List length: 12
node hash: sol | type: 7
node hash: polaris | type: 6
node hash: rigel | type: 1
node hash: pollux | type: 3
node hash: deneb | type: 1
node hash: adhara | type: 7
node hash: betelgeuse | type: 2
node hash: sirio | type: 4
node hash: procyon | type: 1
node hash: altair | type: 5
node hash: achenar | type: 2
node hash: fomalhaut | type: 3
======================== Libera memoria =======================
Creando lista vacia
Agregando constelaciones y misiones:
List length: 28
node hash: geminis | type: 2
node hash: pisis | type: 3
node hash: cefeo | type: 3
node hash: pavo | type: 6
node hash: libra | type: 4
node hash: auriga | type: 2
node hash: sagitario | type: 4
node hash: pavo | type: 0
node hash: crux | type: 3
node hash: cisne | type: 0
node hash: orion | type: 7
node hash: centauro | type: 5
node hash: juno | type: 6
node hash: hubble | type: 2
node hash: irazusta | type: 6
node hash: terra | type: 3
node hash: cassini-huygens | type: 3
node hash: artemis | type: 7
node hash: columbia | type: 1
node hash: kepler | type: 2
node hash: aqua | type: 6
node hash: sputnik | type: 2
node hash: insight | type: 5
node hash: messenger | type: 7
node hash: osiris | type: 1
node hash: rex | type: 0
node hash: chandra | type: 3
node hash: curiosity | type: 2
======================== Libera memoria =======================
======================== Fin del test 1a ========================= Ejercicio 1b ==
Agregando constelaciones y misiones:
junta-constelaciones-mision-estrellas:librarigelcruxlibrajunodenebaurigalunadionelunaisspalas
junta-constelaciones-mision-estrellas:aurigabetelgeusecentaurojunopolluxadharabetelgeusesiriogeminisorioncentaurobetelgeusesiriocefeosagitariocisneganimedesoberontitaniaeris
junta-constelaciones-mision-estrellas:solcisnepavocefeopavopisiscefeosagitariopavocruxrheaencéladovesta
junta-constelaciones-mision-estrellas:cruxpolluxaurigaaurigasagitariohubblelibraaurigacisnelibralunatitanmimastitánapollo 11cassini-huygensceresirisjunohebe
junta-constelaciones-mision-estrellas:pavodenebadharaorionsolprocyonlibracisnepavocisneorioncentaurogeminissolpolarisrigelpavoarielhubblejunochandrayaan-2victoria
junta-constelaciones-mision-estrellas:geminispisiscefeopolarishubblehubblepolluxcruxcalistotritónmirandaartemispallas
junta-constelaciones-mision-estrellas:sagitariorigelsiriodenebachenarpisissagitariopavojunoadharasoyuzhygiea
junta-constelaciones-mision-estrellas:pavopolarisaltaircefeopavocruxpavoioeuropaumbrielgalemede
======================== Fin del test 1b =======================
\ No newline at end of file
== Ejercicio 1a ==
Creando lista vacia
======================== Libera memoria =======================
Creando nodo vacio
======================== Libera memoria =======================
Creando lista vacia
List length: 0
Agregando estrellas:
List length: 12
node hash: sol | type: 7
node hash: polaris | type: 6
node hash: rigel | type: 1
node hash: pollux | type: 3
node hash: deneb | type: 1
node hash: adhara | type: 7
node hash: betelgeuse | type: 2
node hash: sirio | type: 4
node hash: procyon | type: 1
node hash: altair | type: 5
node hash: achenar | type: 2
node hash: fomalhaut | type: 3
======================== Libera memoria =======================
Creando lista vacia
Agregando constelaciones y misiones:
List length: 28
node hash: geminis | type: 2
node hash: pisis | type: 3
node hash: cefeo | type: 3
node hash: pavo | type: 6
node hash: libra | type: 4
node hash: auriga | type: 2
node hash: sagitario | type: 4
node hash: pavo | type: 0
node hash: crux | type: 3
node hash: cisne | type: 0
node hash: orion | type: 7
node hash: centauro | type: 5
node hash: juno | type: 6
node hash: hubble | type: 2
node hash: irazusta | type: 6
node hash: terra | type: 3
node hash: cassini-huygens | type: 3
node hash: artemis | type: 7
node hash: columbia | type: 1
node hash: kepler | type: 2
node hash: aqua | type: 6
node hash: sputnik | type: 2
node hash: insight | type: 5
node hash: messenger | type: 7
node hash: osiris | type: 1
node hash: rex | type: 0
node hash: chandra | type: 3
node hash: curiosity | type: 2
======================== Libera memoria =======================
======================== Fin del test 1a ========================= Ejercicio 1b ==
Agregando constelaciones y misiones:
junta-constelaciones-mision-estrellas:librarigelcruxlibrajunodenebaurigalunadionelunaisspalas
junta-constelaciones-mision-estrellas:aurigabetelgeusecentaurojunopolluxadharabetelgeusesiriogeminisorioncentaurobetelgeusesiriocefeosagitariocisneganimedesoberontitaniaeris
junta-constelaciones-mision-estrellas:solcisnepavocefeopavopisiscefeosagitariopavocruxrheaencéladovesta
junta-constelaciones-mision-estrellas:cruxpolluxaurigaaurigasagitariohubblelibraaurigacisnelibralunatitanmimastitánapollo 11cassini-huygensceresirisjunohebe
junta-constelaciones-mision-estrellas:pavodenebadharaorionsolprocyonlibracisnepavocisneorioncentaurogeminissolpolarisrigelpavoarielhubblejunochandrayaan-2victoria
junta-constelaciones-mision-estrellas:geminispisiscefeopolarishubblehubblepolluxcruxcalistotritónmirandaartemispallas
junta-constelaciones-mision-estrellas:sagitariorigelsiriodenebachenarpisissagitariopavojunoadharasoyuzhygiea
junta-constelaciones-mision-estrellas:pavopolarisaltaircefeopavocruxpavoioeuropaumbrielgalemede
======================== Fin del test 1b =======================
\ No newline at end of file
File added
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include "ej1.h"
#define MAX_TYPE 8
#define RUN(filename, action) pfile=fopen(filename,"a"); action; fclose(pfile);
#define NL(filename) pfile=fopen(filename,"a"); fprintf(pfile,"\n"); fclose(pfile);
char *filename_ej1 = "salida.caso.propio.ej1.txt";
void test_ej1a(char* filename);
void test_ej1b(char* filename);
#if USE_ASM_IMPL
#define string_proc_list_create_impl string_proc_list_create_asm
#define string_proc_node_create_impl string_proc_node_create_asm
#define string_proc_list_add_node_impl string_proc_list_add_node_asm
#define string_proc_list_concat_impl string_proc_list_concat_asm
#else
#define string_proc_list_create_impl string_proc_list_create
#define string_proc_node_create_impl string_proc_node_create
#define string_proc_list_add_node_impl string_proc_list_add_node
#define string_proc_list_concat_impl string_proc_list_concat
#endif
int main() {
srand(0);
remove(filename_ej1);
test_ej1a(filename_ej1);
test_ej1b(filename_ej1);
return 0;
}
void test_ej1a(char* filename)
{
FILE* pfile;
// create an
RUN(filename, fprintf(pfile, "== Ejercicio 1a ==\n");) NL(filename)
RUN(filename, fprintf(pfile, "Creando lista vacia\n");) NL(filename)
string_proc_list* list = string_proc_list_create_impl();
string_proc_list_destroy(list);
RUN(filename, fprintf(pfile, "======================== Libera memoria =======================\n");) NL(filename)
RUN(filename, fprintf(pfile, "Creando nodo vacio\n");) NL(filename)
string_proc_node* node = string_proc_node_create_impl(0, "");
string_proc_node_destroy(node);
RUN(filename, fprintf(pfile, "======================== Libera memoria =======================\n");) NL(filename)
list = string_proc_list_create_impl();
RUN(filename, fprintf(pfile, "Creando lista vacia\n");) NL(filename)
RUN(filename, string_proc_list_print(list, pfile);) NL(filename)
RUN(filename, fprintf(pfile, "Agregando estrellas:\n");) NL(filename)
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sol");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "polaris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rigel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pollux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "deneb");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "adhara");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "betelgeuse");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sirio");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "procyon");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "altair");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "achenar");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "fomalhaut");
RUN(filename, string_proc_list_print(list, pfile);) NL(filename)
RUN(filename, fprintf(pfile, "======================== Libera memoria =======================\n");) NL(filename)
string_proc_list_destroy(list);
RUN(filename, fprintf(pfile, "Creando lista vacia\n");) NL(filename)
list = string_proc_list_create_impl();
RUN(filename, fprintf(pfile, "Agregando constelaciones y misiones:\n");) NL(filename)
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "geminis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pisis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "orion");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "centauro");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hubble");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "irazusta");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "terra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cassini-huygens");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "artemis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "columbia");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "kepler");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "aqua");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sputnik");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "insight");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "messenger");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "osiris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rex");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "chandra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "curiosity");
RUN(filename, string_proc_list_print(list, pfile);) NL(filename)
RUN(filename, fprintf(pfile, "======================== Libera memoria =======================\n");) NL(filename)
string_proc_list_destroy(list);
RUN(filename, fprintf(pfile, "======================== Fin del test 1a =======================");)
}
void test_ej1b(char* filename)
{
FILE* pfile;
// create an
RUN(filename, fprintf(pfile, "== Ejercicio 1b ==\n");) NL(filename)
string_proc_list* list = string_proc_list_create_impl();
RUN(filename, fprintf(pfile, "Agregando constelaciones y misiones:\n");) NL(filename)
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "geminis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pisis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sol");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "polaris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rigel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pollux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "deneb");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "adhara");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "betelgeuse");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sirio");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "orion");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "centauro");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hubble");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sol");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "polaris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rigel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pollux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "deneb");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "adhara");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "betelgeuse");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sirio");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "procyon");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "altair");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "achenar");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "geminis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pisis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "orion");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "centauro");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hubble");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "geminis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pisis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "orion");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "centauro");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hubble");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sol");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "polaris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rigel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pollux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "deneb");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "adhara");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "betelgeuse");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sirio");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cefeo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "libra");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "auriga");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "sagitario");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pavo");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "crux");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cisne");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "luna");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "ganimedes");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "titan");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "calisto");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "io");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "europa");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "luna");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "oberon");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "titania");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "rhea");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "tritón");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "encélado");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "mimas");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "titán");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "dione");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "luna");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "umbriel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "ariel");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "miranda");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "galemede");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "apollo 11");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "soyuz");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "iss");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hubble");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "cassini-huygens");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "artemis");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "chandrayaan-2");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "ceres");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "vesta");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "pallas");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hygiea");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "iris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "eris");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "juno");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "hebe");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "palas");
string_proc_list_add_node_impl(list, rand() % MAX_TYPE, "victoria");
char* new_hash_1 = string_proc_list_concat_impl(list, 0, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_1);)
free(new_hash_1);
char* new_hash_2 = string_proc_list_concat_impl(list, 1, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_2);)
free(new_hash_2);
char* new_hash_3 = string_proc_list_concat_impl(list, 2, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_3);)
free(new_hash_3);
char* new_hash_4 = string_proc_list_concat_impl(list, 3, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_4);)
free(new_hash_4);
char* new_hash_5 = string_proc_list_concat_impl(list, 4, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_5);)
free(new_hash_5);
char* new_hash_6 = string_proc_list_concat_impl(list, 5, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_6);)
free(new_hash_6);
char* new_hash_7 = string_proc_list_concat_impl(list, 6, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_7);)
free(new_hash_7);
char* new_hash_8 = string_proc_list_concat_impl(list, 7, "junta-constelaciones-mision-estrellas:");
RUN(filename, fprintf(pfile, "%s\n",new_hash_8);)
free(new_hash_8);
string_proc_list_destroy(list);
RUN(filename, fprintf(pfile, "======================== Fin del test 1b =======================");)
}
CC=c99
CFLAGS= -Wall -Wextra -pedantic -O0 -g -lm -Wno-unused-variable -Wno-unused-parameter -no-pie -z noexecstack
NASM=nasm
NASMFLAGS=-f elf64 -g -F DWARF
all: main tester
OBJS := ej2_c.o ej2_asm.o
tester: tester.c $(OBJS)
$(CC) $(CFLAGS) $^ -o $@
main: main.c $(OBJS)
$(CC) $(CFLAGS) $^ -o $@
ej2_c.o: ej2.c ej2.h
$(CC) $(CFLAGS) -c $< -o $@
ej2_asm.o: ej2.asm ej2.h
$(NASM) $(NASMFLAGS) $< -o $@
clean:
rm -f *.o
rm -f main tester
rm -f salida.propios.*
global combinarImagenes_asm
section .data
mascara_setear_alpha: DD 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000
mascara_shuffle_caso_1_comparacion: DB 1, 1, 1, 1, 5, 5, 5, 5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
mascara_suma_componente_b_shuffle: DB 2, 0xff, 0xff, 0xff, 6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
mascara_suma_componente_b_and: DD 0x000000FF, 0x000000FF, 0x00, 0x00
mascara_resta_componente_r_shuffle: DB 0xff, 0xff, 0, 0xff, 0xff, 0xff, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
mascara_resta_componente_r_and: DD 0x00FF0000, 0x00FF0000, 0x00, 0x00
mascara_resta_componente_g_and: DD 0x0000FF00, 0x0000FF00, 0x00, 0x00
mascara_todos_unos: DD 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
;########### SECCION DE TEXTO (PROGRAMA)
section .text
; Signatura de la función:
; void combinarImagenes(uint8_t *src1, uint8_t *src2, uint8_t *dst, uint32_t width, uint32_t height)
; Mapeo de parámetros a registros:
; rdi[src1]. rsi[src2], rdx[dst], rcx[width], r8[height]
; CASO 1) A[ij] G > B[ij] G
; la idea en el caso 1 es guardar en un xmm solo los componentes G del pixel de A y en otro xmm solo los componentes G del pixel de B
; Así puedo hacer la comparación:
; | AG | AG | AG | AG | > | BG | BG | BG | BG |
; De este modo descarto los píxeles que no cumplen la primera condición
; En el caso 2 simplemente es negar el resultado de esa comparación
; La máscara del shufle que me sirve para esto es: | 1 | 1 | 1 | 1 | 5 | 5 | 5 | 5 | ff | ff | ff | ff | ff | ff | ff | ff |
; Pues el índice del valor green es el 1 si pensamos los xmm en 16 paquetes de 8 bits
combinarImagenes_asm:
PUSH rbp
MOV rbp, rsp
; cuerpo
; 1. Busco la cantidad de pixeles a pintar: width * height
MOV RAX, R8 ; Me traigo el alto a rax
MUL RCX ; Multiplico el ancho x alto
.pintar_pixeles:
; 2. Cargo 2 pixeles a registros, para luego verificar a que caso pertenecen y pintarlos de esa manera en el destino
MOVQ XMM1, [RDI] ; XMM = B1 G1 R1 A1 B2 G2 R2 A2 XX XX XX XX XX XX XX XX (128 bits) (2 PIXELES DE LA IMAGEN A)
MOVQ XMM2, XMM1
MOVQ XMM3, [RSI] ; (2 PIXELES DE LA IMAGEN B)
MOVQ XMM4, XMM3
; CASO 1) A[ij] G > B[ij] G:
MOVDQU XMM5, [mascara_shuffle_caso_1_comparacion]
PSHUFB XMM1, XMM5 ; XMM1 = | AG1 | AG1 | AG1 | AG1 | AG2 | AG2 | AG2 | AG2 | XX | XX | XX | XX | XX | XX | XX | XX |
PSHUFB XMM3, XMM5 ; XMM2 = | BG1 | BG1 | BG1 | BG1 | BG2 | BG2 | BG2 | BG2 | XX | XX | XX | XX | XX | XX | XX | XX |
PCMPGTB XMM1, XMM3 ; HAGO LA COMPARACIÓN DE LAS COMPONENTES G DE AMBOS PÍXELES: A[ij] G > B[ij] G, GUARDO EL RESULTADO EN XMM1
PAND XMM2, XMM1 ; GUARDO EN XMM2 LOS PIXELES DE A QUE CUMPLEN LA CONDICION
PAND XMM4, XMM1 ; GUARDO EN XMM4 LOS PIXELES DE B QUE CUMPLEN LA CONDICION
MOVQ XMM1, XMM2 ; ME GUARDO UNA COPIA DE LOS PIXELES DE A QUE CUMPLEN LA CONDICION
MOVQ XMM7, XMM2 ; ME GUARDO UNA COPIA DE LOS PIXELES DE A QUE CUMPLEN LA CONDICION
MOVQ XMM9, XMM2 ; ME GUARDO UNA COPIA DE LOS PIXELES DE A QUE CUMPLEN LA CONDICION
MOVQ XMM3, XMM4 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
MOVQ XMM8, XMM4 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
MOVQ XMM10, XMM4 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
; Ahora quiero sumarle a la componente B del pixel de A la componente R del pixel de B:
MOVQ XMM6, [mascara_suma_componente_b_shuffle]
PSHUFB XMM4, XMM6
; AL HACER ESTE SHUFLE CON ESA MÁSCARA CON LOS PIXELES DE B QUE CUMPLEN LA CONDICION, LO QUE HAGO ES PONER EL VALOR DE LA COMPONENTE
; R DE LOS PÍXELES DE B EN LA POSICION CORRESPONDIENTE A LA COMPONENTE B DE LOS PIXELES DE A Y CERO EN EL RESTO DE LOS COMPONENTES
MOVQ XMM6, [mascara_suma_componente_b_and]
PAND XMM2, XMM6
; AL HACER ESTE AND CON LOS PIXELES DE LA IMAGEN A, LO QUE HAGO ES MANTENER SOLAMENTE EL VALOR DE LOS COMPONENTES B Y PONER EL RESTO EN CERO
; DE ESTE MODO PUEDO HACER LA SUMA: A[ij]B + B[ij]R
PADDB XMM2, XMM4
; AHORA TENGO EN XMM2:
; | AB1 + BR1 | 0 | 0 | 0 | AB2 + BR2 | 0 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; AHORA QUIERO RESTARLE A LA COMPONENTE BLUE DEL PIXEL DE LA IMAGEN B EL COMPONENTE RED DEL PIXEL DE LA IMAGEN A
; HAGO ALGO PARECIDO A LO QUE HICE ANTERIORMENTE:
MOVQ XMM4, XMM3 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION EN XMM4
MOVQ XMM6, [mascara_resta_componente_r_shuffle]
PSHUFB XMM4, XMM6
; AL HACER ESTE SHUFFLE CON ESA MASCARA CON LOS PIXELES DE B QUE CUMPLEN LA CONDICION, LO QUE HAGO ES PONER EL VALOR DE LA COMPONENTE
; BLUE DE LOS PIXELES DE B EN LA POSICION CORRESPONDIENTE A LA COMPONENTE RED Y CERO EN EL RESTO DE LOS COMPONENTES
MOVQ XMM8, XMM4 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
; AHORA TENGO EN XMM4:
; | 0 | 0 | BB1 - AR1 | 0 | 0 | 0 | BB2 - AR2 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; AHORA QUIERO RESTARLE A LA COMPONENTE GREEN DE A LA COMPONENTE GREEN DE B:
MOVQ XMM6, [mascara_resta_componente_g_and]
PAND XMM7, XMM6 ; PIXELES DE A
PAND XMM8, XMM6 ; PIXELES DE B
; AL HACER ESTOS AND CON LOS PIXELES DE A (GUARDADOS EN XMM7) Y LOS PIXELES DE B (GUARDADOS EN XMM8) LO QUE HAGO ES QUEDARME SOLAMENTO
; CON LOS COMPONENTES GREEN DE CADA LOS PIXELES Y PONER EN CERO EL RESTO
; DE ESTE MODO AHORA PUEDO HACER B[ij] B − A[ij] R
PSUBB XMM7, XMM8
; AHORA TENGO EN XMM7:
; | 0 | AG1 - BG1 | 0 | 0 | 0 | AG2 - BG2 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; RESUMIENDO:
; TENGO EN XMM2:
; | AB1 + BR1 | 0 | 0 | 0 | AB2 + BR2 | 0 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; TENGO EN XMM4:
; | 0 | 0 | BB1 - AR1 | 0 | 0 | 0 | BB2 - AR2 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; TENGO EN XMM7:
; | 0 | AG1 - BG1 | 0 | 0 | 0 | AG2 - BG2 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; AHORA ME FALTA UNIRLOS:
POR XMM2, XMM4
POR XMM2, XMM7
; Ahora tengo en XMM2 LOS PIXELES QUE ENTRAN EN EL CASO 1 YA PROCESADOS, SOLO FALTA PONER LAS COMPONENTE ALPHA EN 255
; LO HAG0 AL FINAL DE TODO YA QUE TENGO QUE HACERLO PARA AMBOS CASOS
; CASO 2) !(A[ij] G > B[ij] G) :
; HAGO LA COMPARACIÓN COMO EL PRIMER CASO Y LA NIEGO:
; TENGO EN XMM9 LOS PIXELES DE A
; TENGO EN XMM10 LOS PIXELES DE B
; ME HAGO UNAS COPIAS MÁS:
MOVDQU XMM11, XMM9
MOVDQU XMM12, XMM10
MOVDQU XMM5, [mascara_shuffle_caso_1_comparacion]
PSHUFB XMM11, XMM5 ; XMM1 = | AG1 | AG1 | AG1 | AG1 | AG2 | AG2 | AG2 | AG2 | XX | XX | XX | XX | XX | XX | XX | XX |
PSHUFB XMM12, XMM5 ; XMM2 = | BG1 | BG1 | BG1 | BG1 | BG2 | BG2 | BG2 | BG2 | XX | XX | XX | XX | XX | XX | XX | XX |
PCMPGTB XMM11, XMM12 ; HAGO LA COMPARACIÓN DE LAS COMPONENTES G DE AMBOS PÍXELES: A[ij] G > B[ij] G, GUARDO EL RESULTADO EN XMM1
; AHORA TENGO QUE NEGAR EL RESULTADO DE XMM11:
MOVDQU XMM6, [mascara_todos_unos]
PXOR XMM11, XMM6
; AHORA TENGO EN XMM11 UNOS EN LA POSICIONES DE LOS PIXELES QUE ENTRAN EN EL CASO 2 Y CERO EN LOS QUE NO
PAND XMM9, XMM11 ; GUARDO EN XMM9 LOS PIXELES DE A QUE CUMPLEN LA CONDICION
PAND XMM10, XMM11 ; GUARDO EN XMM10 LOS PIXELES DE B QUE CUMPLEN LA CONDICION
MOVQ XMM3, XMM9 ; ME GUARDO UNA COPIA DE LOS PIXELES DE A QUE CUMPLEN LA CONDICION
MOVQ XMM4, XMM9 ; ME GUARDO UNA COPIA DE LOS PIXELES DE A QUE CUMPLEN LA CONDICION
MOVQ XMM5, XMM10 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
MOVQ XMM6, XMM10 ; ME GUARDO UNA COPIA DE LOS PIXELES DE B QUE CUMPLEN LA CONDICION
; ESTO ES IGUAL AL CASO 1
; Ahora quiero sumarle a la componente B del pixel de A la componente R del pixel de B:
MOVQ XMM14, [mascara_suma_componente_b_shuffle]
PSHUFB XMM5, XMM14
; AL HACER ESTE SHUFLE CON ESA MÁSCARA CON LOS PIXELES DE B QUE CUMPLEN LA CONDICION, LO QUE HAGO ES PONER EL VALOR DE LA COMPONENTE
; R DE LOS PÍXELES DE B EN LA POSICION CORRESPONDIENTE A LA COMPONENTE B DE LOS PIXELES DE A Y CERO EN EL RESTO DE LOS COMPONENTES
MOVQ XMM14, [mascara_suma_componente_b_and]
PAND XMM3, XMM14
; AL HACER ESTE AND CON LOS PIXELES DE LA IMAGEN A, LO QUE HAGO ES MANTENER SOLAMENTE EL VALOR DE LOS COMPONENTES B Y PONER EL RESTO EN CERO
; DE ESTE MODO PUEDO HACER LA SUMA: A[ij]B + B[ij]R
PADDB XMM3, XMM5
; AHORA TENGO EN XMM3:
; | AB1 + BR1 | 0 | 0 | 0 | AB2 + BR2 | 0 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; ESTO TAMBIPEN ES IGUAL AL CASO 1:
; AHORA QUIERO RESTARLE A LA COMPONENTE BLUE DEL PIXEL DE LA IMAGEN B EL COMPONENTE RED DEL PIXEL DE LA IMAGEN A
; HAGO ALGO PARECIDO A LO QUE HICE ANTERIORMENTE:
MOVQ XMM14, [mascara_resta_componente_r_shuffle]
PSHUFB XMM6, XMM6
; AL HACER ESTE SHUFFLE CON ESA MASCARA CON LOS PIXELES DE B QUE CUMPLEN LA CONDICION, LO QUE HAGO ES PONER EL VALOR DE LA COMPONENTE
; BLUE DE LOS PIXELES DE B EN LA POSICION CORRESPONDIENTE A LA COMPONENTE RED Y CERO EN EL RESTO DE LOS COMPONENTES
MOVQ XMM14, [mascara_resta_componente_r_and]
PAND XMM4, XMM6
; AL HACER ESTE AND CON LOS PIXELES DE LA IMAGEN A, LO QUE HAGO ES MANTENER SOLAMENTE EL VALOR DE LOS COMPONENTES RED Y PONER EL RESTO EN CERO
; DE ESTE MODO PUEDO HACER LA RESTA: B[ij]B - A[ij]R
PSUBB XMM6, XMM14
; AHORA TENGO EN XMM6:
; | 0 | 0 | BB1 - AR1 | 0 | 0 | 0 | BB2 - AR2 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; ESTO SÍ ES DIFERENTE AL CASO 1:
; AHORA QUIERO HACER res[ij]G = promedio(A[ij] G , B[ij] G )
MOVQ XMM14, [mascara_resta_componente_g_and]
PAND XMM9, XMM6 ; PIXELES DE A
PAND XMM10, XMM6 ; PIXELES DE B
; AL HACER ESTOS AND CON LOS PIXELES DE A (GUARDADOS EN XMM7) Y LOS PIXELES DE B (GUARDADOS EN XMM8) LO QUE HAGO ES QUEDARME SOLAMENTO
; CON LOS COMPONENTES GREEN DE CADA LOS PIXELES Y PONER EN CERO EL RESTO
; DE ESTE MODO AHORA PUEDO USAR pavgb PARA CALCULAR EL PROMEDIO:
pavgb XMM9, XMM10
; AHORA TENGO EN XMM9:
; | 0 | PROMEDIO(AG1, BG1) | 0 | 0 | 0 | PROMEDIO(AG2, BG2) | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; RESUMIENDO:
; TENGO EN XMM3:
; | AB1 + BR1 | 0 | 0 | 0 | AB2 + BR2 | 0 | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; TENGO EN XMM6:
; | 0 | 0 | BB1 - AR1 | 0 | 0 | 0 | BB2 - AR2 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; TENGO EN XMM9:
; | 0 | PROMEDIO(AG1, BG1) | 0 | 0 | 0 | PROMEDIO(AG2, BG2) | 0 | 0 | XX | XX | XX | XX | XX | XX | XX | XX |
; AHORA ME FALTA UNIRLOS:
POR XMM3, XMM6
POR XMM3, XMM9
; AHORA TENGO EN XMM2 LOS PIXELES DEL CASO 1 Y EN XMM3 LOS PIXELES DEL CASO 2, LOS UNO
POR XMM2, XMM3
; AHORA PONGO LA COMPONENTE ALPHA EN 255:
MOVDQU XMM4, [mascara_setear_alpha]
POR XMM2, XMM4
; AHORA TENGO EN XMM2 LOS DOS PIXELES LISTOS PARA CARGAR EN MEMORIA:
; 4. Ahora tengo los píxeles finales a guardar en el destino
MOVQ [RDX], XMM2
; 4.2 Avanzo a los siguientes
ADD RDI, 8
ADD RSI, 8 ; avanzo el RSI 8 bytes (4 píxeles)
ADD RDX, 8
SUB RAX, 2
CMP RAX, 0
JNZ .pintar_pixeles
XOR rax, rax
; epílogo
POP rbp
RET
ret
\ No newline at end of file
#include "ej2.h"
void combinarImagenes(uint8_t *src_a, uint8_t *src_b, uint8_t *dst, uint32_t width, uint32_t height)
{
}
#ifndef EJ2
#define EJ2
#include <stdio.h> //encabezado de funciones de entrada y salida fopen, fclose, fgetc, printf, fprintf ...
#include <stdlib.h> //biblioteca estándar, atoi, atof, rand, srand, abort, exit, system, NULL, malloc, calloc, realloc...
#include <stdint.h> //contiene la definición de tipos enteros ligados a tamaños int8_t, int16_t, uint8_t,...
#include <ctype.h> //contiene funciones relacionadas a caracteres, isdigit, islower, tolower...
#include <string.h> //contiene las funciones relacionadas a strings, memcmp, strcat, memset, memmove, strlen,strstr...
#include <math.h> //define funciones matemáticas como cos, sin, abs, sqrt, log...
#include <stdbool.h> //contiene las definiciones de datos booleanos, true (1), false (0)
#include <unistd.h> //define constantes y tipos standard, NULL, R_OK, F_OK, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO...
#include <assert.h> //provee la macro assert que evalúa una condición, y si no se cumple provee información diagnóstica y aborta la ejecución
//*************************************
//Declaración de estructuras
//*************************************
typedef struct bgra_t {
unsigned char b, g, r, a;
} __attribute__((packed)) bgra_t;
#define USE_ASM_IMPL 1
//*******************************
//Declaración de funciones de ej2
//*******************************
void combinarImagenes(uint8_t *src_a, uint8_t *src_b, uint8_t *dst, uint32_t width, uint32_t height);
void combinarImagenes_asm(uint8_t *src_a, uint8_t *src_b, uint8_t *dst, uint32_t width, uint32_t height);
#endif /* EJ2 */
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