Diferencia entre revisiones de «Parcial del 10/10/06 (Organización del Computador II)»

De Cuba-Wiki
Sin resumen de edición
 
Línea 1: Línea 1:
Para mi la dw menos significativa es la primera, no la ultima como vi que estaba hecho en la Resta.
== Ejercicio 1 (IA32) ==
O sea, si NGde es
Codigo ASM de las funciones
  int tam
Nota a tener en cuenta: tal vez si no hubiese usado las macros que recomendo Tute me hubiese salido todo mas facil...
  void *r


los 32 bits menos significativos son a los que apunta r, no [r + tam -4]


por favor, corrijanme si me estoy equivocando
; Definiciones para Windows
%ifdef win32
%define SumaMiniI _SumaMiniI
%define RestaNxDI _RestaNxDI
%define malloc _malloc
%endif
; Tal como le prometimos a C, aca estan las funciones
global RestaNxDI
global SumaMiniI
; El malloc lo tengo definido afuera
extern malloc
; Comienzo del codigo
section .text
;-------------------------------------------------------------------
; Macros que tute recomendo hacer
;-------------------------------------------------------------------
; Inicio del stack frame
%macro SF_ini 0
push ebp
mov ebp, esp
push esi
push edi
push ebx
%endmacro
; Fin del stack frame
%macro SF_fin 0
pop ebx
pop edi
pop esi
pop ebp
ret
%endmacro
; Lee un NGde de una posicion de memoria y asigna su tam a %1 y su r a %2
%macro LevantarNGde 3
%define reg_tam %1
%define reg_r %2
%define pNGde %3
mov dword reg_tam, [pNGde]
mov dword reg_r, [pNGde + 4]
%endmacro
; Levanta un NGde pero de tam solo 1, 2 o 4 apuntado por %2 y deja su correspondiente numero de 32 bits en reg_valor
%macro LevantarNGdeMini 2
%define reg_valor %1
%define pNGde %2
; Levanto el NGde...
LevantarNGde eax, ecx, pNGde
; ...y me fijo como expandir el signo segun el tamaño con el que vino
;xor reg_valor, reg_valor
cmp eax, 2
jl %%_uno
je %%_dos
%%_cuatro:
mov reg_valor, [ecx]
jmp %%_fin
%%_dos:
mov ax, [ecx]
cwde
mov reg_valor, eax
jmp %%_fin
%%_uno:
mov al, [ecx]
cbw
cwde
mov reg_valor, eax
%%_fin:
%endmacro
; Crea un nuevo NGde de tamaño %1. Deja a eax apuntandolo y en edi a r
%macro NuevoNGde 1
%define tam %1
; Pido para r
push dword tam
call malloc
add esp, 4
mov edi, eax
; Pido para el NGde
push dword 8
call malloc
add esp, 4
; Le informo cual es su tamaño y adonde tiene su numero (r)
mov dword [eax], tam
mov dword [eax + 4], edi
%endmacro
;-------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; NGde* SumaMiniI(Ngde *sumando1, NGde *sumando2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SumaMiniI:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; eax = ret
; ebx = sumando1 (alto)
; ecx = sumando2 (bajo)
; edx = sumando2 (alto)
; edi = ret->r
; esi = sumando1 (bajo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SF_ini
; Cargo los 2 sumandos de parametro y extiendo los valores de 4 a 8 bytes. Si metiese de parametro a la macro [ebp + ...] terminaria haciendo
; doble indireccion en algun momento, asique mejor asi
mov edx, [ebp + 8]
LevantarNGdeMini eax, edx
cdq
mov esi, eax
mov ebx, edx
mov edx, [ebp + 12]
LevantarNGdeMini eax, edx
cdq
mov ecx, eax
; Sumo la parte baja de los sumandos y la alta con carry, por si la suma de los bajos tiro un carry
add esi, ecx
adc ebx, edx
; Creo el NGde de retorno (siempre de tamaño 8) y guardo el puntero en ecx
NuevoNGde 8
; Agrego las dos mitades del resultado
mov dword [edi + 4], esi
mov dword [edi], ebx
SF_fin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; NGde* RestaNxDI(NGde *minuendo, NGde *sustraendo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RestaNxDI:
SF_ini
mov ebx, [ebp + 8] ; ebx -> minuendo
; Creo el retorno con 4 bytes mas que el minuendo
mov esi, [ebx] ; esi -> minuendo.tam
add esi, 4
NuevoNGde esi ; eax -> ret, edi = ret.r
push eax ; Guardo el valor de retorno asi ahora lo puedo pisotear felizmente
mov ecx, [ebx] ; recupero el minuendo.tam en ecx
; Cargo el valor del sustraendo, total es de 4 bytes
mov esi, [ebp + 12] ; esi -> sustraendo
mov edx, [esi + 4] ; edx = sustraendo.r
mov edx, [edx] ; edx = *(sustraendo.r)
; Le resto el sustraendo al dword menos significativo del minuendo y ya voy guardando en ret
mov eax, [ebx + 4] ; eax -> minuendo.r
mov esi, [eax + ecx - 4] ; esi = LSdword del minuendo.r
sub esi, edx ; esi = la resta de los dwords mas bajos
mov dword [edi + ecx], esi ; Guardo en el LSdword del ret.r, a este no le resto 4 porque tiene 4 bytes mas que el minuendo
; Ahora voy a ir recorriendo todos los dwords restando los burrows que se pudieron haber formado
; hasta que no tenga carry o me quede sin mas minuendo
_bucle_burrow:
dec ecx ; Hago esta chanchada para no alterar el carry
dec ecx
dec ecx
dec ecx
jz _fin_bucle_burrow ; Si no tengo mas tamaño a quien pedirle, termine. En algun momento va a ser 0 porque minuendo.tam mod 4 = 0 y voy restando de a 4
mov esi, [eax + ecx - 4] ; Cargo el dword del minuendo.r
sbb esi, 0 ; Le resto solo el posible burrow (o carry)
mov dword [edi + ecx], esi ; Escribo en el ret.r
jmp _bucle_burrow
_fin_bucle_burrow:
; Por ultimo, tengo que decidir si los 4 bytes de sobra que tiene el ret son extendidos de positivo o negativo.
cmp dword esi, 0
jl _neg
_pos:
mov dword [edi], 0x00000000
jmp _sig
_neg:
mov dword [edi], 0xFFFFFFFF
_sig:
pop eax ; Recupero el puntero al ret que habia pisoteado felizmente
SF_fin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
Codigo en C para probar las funciones
 
#include <stdio.h>
#include <stdlib.h>
/* Hice que la estructura sea un tipo asi mejoraba la sintaxis, en el fondo son lo mismo */
typedef struct{int tam; int *r;} NGde;
/* Le juramos a C que vamos a definirle estas funciones afuera */
extern NGde* SumaMiniI(NGde *sumando1, NGde *sumando2);
extern NGde* RestaNxDI(NGde *minuendo, NGde *sustraendo);
/* Muestra un NGde por pantalla */
void MostrarNGde(const NGde n)
{
/* Notar que como r es puntero a int hay que sumar solo 1 para avanzar un dword (sizeof(int) == 4) */
int i = 0;
while(i < n.tam)
{
printf("%p ", *(n.r + i / 4));
i = i + 4;
}
}
/************* Rutina de pruebas de la primer funcion *************/
void PruebasSumaMiniI()
{
/* Declaro 4 NGdes para usar de ejemplo y 3 punteros que van a apuntar a sus sumas */
NGde a;
NGde b;
NGde c;
NGde d;
NGde e;
NGde *s1;
NGde *s2;
NGde *s3;
/* Inicializo los 4 NGdes con algunos valores */
a.tam = 4;
a.r = malloc(a.tam);
*(a.r) = 0xFFFFFFFF;
printf("a.tam: %u, *(a.r): ", a.tam);
MostrarNGde(a);
printf("\n");
b.tam = 1;
b.r = malloc(b.tam);
*(b.r) = 0x0B;
printf("b.tam: %u, *(b.r): ", b.tam);
MostrarNGde(b);
printf("\n");
c.tam = 2;
c.r = malloc(c.tam);
*(c.r) = 0x4513;
printf("c.tam: %u, *(c.r): ", c.tam);
MostrarNGde(c);
printf("\n");
d.tam = 2;
d.r = malloc(d.tam);
*(d.r) = 0xE320;
printf("d.tam: %u, *(d.r): ", d.tam);
MostrarNGde(d);
printf("\n");
e.tam = 4;
e.r = malloc(e.tam);
*(e.r) = 0xFFFFFFFF;
printf("e.tam: %u, *(e.r): ", e.tam);
MostrarNGde(e);
printf("\n");
/* Tres sumas de ejemplo */
s1 = SumaMiniI(&a, &b);
printf("s1->tam: %u, *(s1->r): ", s1->tam);
MostrarNGde(*s1);
printf("\n");
s2 = SumaMiniI(&c, &d);
printf("s2->tam: %u, *(s2->r): ", s2->tam);
MostrarNGde(*s2);
printf("\n");
s3 = SumaMiniI(&e, &a);
printf("s3->tam: %u, *(s3->r): ", s3->tam);
MostrarNGde(*s3);
printf("\n");
/* Los leaks son mala onda */
free(s1->r); free(s2->r); free(s1); free(s2);
}
/************* Rutina de pruebas de la segunda funcion *************/
void PruebasRestaNxDI()
{
/* Declaro 4 NGdes para usar de ejemplo y 3 punteros que van a apuntar a sus restas */
NGde a;
NGde b;
NGde c;
NGde d;
NGde *r1;
NGde *r2;
NGde *r3;
/* Inicializo los 4 NGdes con algunos valores */
a.tam = 4;
a.r = malloc(a.tam);
*(a.r) = 0x00000100;
printf("a.tam: %u, *(a.r): ", a.tam);
MostrarNGde(a);
printf("\n");
b.tam = 4;
b.r = malloc(b.tam);
*(b.r) = 0x0000000A;
printf("b.tam: %u, *(b.r): ", b.tam);
MostrarNGde(b);
printf("\n");
c.tam = 12;
c.r = malloc(c.tam);
*(c.r) = 0xAE3490F1;
*(c.r + 1) = 0xAE3490F1;
*(c.r + 2) = 0xAE3490F1;
printf("c.tam: %u, *(c.r): ", c.tam);
MostrarNGde(c);
printf("\n");
d.tam = 32;
d.r = malloc(d.tam);
*(d.r) = 0;
*(d.r + 1) = 0;
*(d.r + 2) = 0;
*(d.r + 3) = 0;
*(d.r + 4) = 0;
*(d.r + 5) = 0;
*(d.r + 6) = 0;
*(d.r + 7) = 0;
printf("d.tam: %u, *(d.r): ", d.tam);
MostrarNGde(d);
printf("\n");
/* Tres restas de ejemplo */
r1 = RestaNxDI(&b, &a);
printf("r1->tam: %u, *(r1->r): ", r1->tam);
MostrarNGde(*r1);
printf("\n");
r2 = RestaNxDI(&c, &a);
printf("r2->tam: %u, *(r2->r): ", r2->tam);
MostrarNGde(*r2);
printf("\n");
r3 = RestaNxDI(&d, &a);
printf("r3->tam: %u, *(r3->r): ", r3->tam);
MostrarNGde(*r3);
printf("\n");
/* Los leaks son mala onda */
free(r1->r); free(r2->r); free(r3->r); free(r1); free(r2); free(r3);
}
/************* Punto de entrada ****************/
int main(int argc, char *argv[])
{
printf(" .................. Pruebas de SumaMiniI .................. \n");
PruebasSumaMiniI();
printf("\n\n .................. Pruebas de RestaNxDI .................. \n");
PruebasRestaNxDI();
return 0;
}
 
 
Makefile para compilar los dos archivos
 
RM= rm
NASM = nasm
# optimization
#
OPT= -g -ggdb -O2
# flags for ANSI compiles
#
CFLAGS= -pedantic -ansi -Wall ${OPT}
# ANSI compiler
#
GCC= gcc
OBJ=main.o parcial.o
OTHEROBJ=
INCS=
MAIN=parcial
.PHONY: all win linux
all:
@echo Debe elegir alguno de los sistemas operativos \(win, linux\). Ejemplo:
@echo  make linux
win:
make NOPT="-fwin32 -Dwin32"  ${MAIN}
linux:
make NOPT=-felf ${MAIN}
${MAIN}: ${OBJ} ${OTHEROBJ} $(INCS)
${GCC} ${CFLAGS} -o ${MAIN} ${OBJ} ${OTHEROBJ}
%.o: %.asm
${NASM} ${NOPT} -O1 $< -o $@
%.o: %.c
${GCC} ${CFLAGS} -c $< -o $@
clean:
${RM} -f ${OBJ} ${OTHEROBJ} ${MAIN}
install: all
${CAT} ${MAIN} > /dev/null
 
Notar que solo hay que poner "make win" o "make linux".
 
 
== Ejercicio 2 (IA64) ==
 
a) signo
 
.proc signo
signo:
    alloc loc0 = ar.pfs,1,1,0,0
   
    cmp.eq p1,p2 = 0, in0
    (p1) mov r8 = 0
    (p2) cmp.gts.unc p3, p4 = 0, in0
    (p3) mov r8 = -1
    (p4) mov r8 = 1
    mov ar.pfs = loc0
    br.ret.sptk.many b0
.endp signo
 
b) Listas
 
.proc listas
listas:
    alloc loc0 = ar.pfs,5,3,1,0
    mov ar.lc = in4 // in4=N
    mov loc1 = b0 //guarda el branch
loop:
    ld8 loc2 = [in0], 8
    mov out0 = loc2
    br.call b0 = signo
    cmp.eq p1,p2 = 0, r8
    (p1) st8 [in3] = loc2, 8 // in3 = ceros
    (p2) cmp.gts.unc p3, p4 = 0, r8
    (p3) st8 [in2] = loc2, 8 // negativos
    (p4) st8 [in1] = loc2, 8 // positivos
    br.cloop loop
   
    st8 [in1] = r0
    st8 [in2] = r0
    st8 [in3] = -1
   
    mov b0 = loc1
    mov ar.pfs = loc0
    br.ret.sptk.many bo  //termina la locura
 
 
Para Patricia esto estaba bien, espero que lo este para uds.

Revisión del 00:49 4 dic 2006

Ejercicio 1 (IA32)

Codigo ASM de las funciones Nota a tener en cuenta: tal vez si no hubiese usado las macros que recomendo Tute me hubiese salido todo mas facil...


; Definiciones para Windows
%ifdef win32
	%define SumaMiniI			_SumaMiniI
	%define RestaNxDI 			_RestaNxDI
	%define malloc				_malloc
%endif

; Tal como le prometimos a C, aca estan las funciones
global 			RestaNxDI
global 			SumaMiniI

; El malloc lo tengo definido afuera
extern 			malloc

; Comienzo del codigo
section .text

;-------------------------------------------------------------------
; Macros que tute recomendo hacer
;-------------------------------------------------------------------
; Inicio del stack frame
%macro SF_ini	0
	push 		ebp
	mov			ebp,	esp
	push 		esi
	push 		edi
	push 		ebx
%endmacro

; Fin del stack frame
%macro SF_fin	0
	pop ebx
	pop edi
	pop esi
	pop ebp
	ret
%endmacro

; Lee un NGde de una posicion de memoria y asigna su tam a %1 y su r a %2
%macro LevantarNGde		3
	%define		reg_tam		%1
	%define		reg_r		%2
	%define		pNGde		%3
	mov		dword		reg_tam,	[pNGde]
	mov		dword		reg_r,		[pNGde + 4]
%endmacro

; Levanta un NGde pero de tam solo 1, 2 o 4 apuntado por %2 y deja su correspondiente numero de 32 bits en reg_valor
%macro LevantarNGdeMini		2
	%define		reg_valor	%1
	%define		pNGde		%2
	; Levanto el NGde...
	LevantarNGde	eax,		ecx,		pNGde
	
	; ...y me fijo como expandir el signo segun el tamaño con el que vino
	;xor		reg_valor,	reg_valor
	cmp		eax,		2
	jl		%%_uno
	je		%%_dos
		%%_cuatro:
			mov		reg_valor,		[ecx]
			jmp		%%_fin
		%%_dos:
			mov		ax,		[ecx]
			cwde
			mov		reg_valor,		eax
			jmp		%%_fin
		%%_uno:
			mov		al,		[ecx]
			cbw
			cwde
			mov		reg_valor,		eax
	%%_fin:
%endmacro

; Crea un nuevo NGde de tamaño %1. Deja a eax apuntandolo y en edi a r
%macro NuevoNGde	1
	%define	tam			%1
	; Pido para r
	push	dword		tam
	call	malloc
	add		esp,		4
	mov		edi,		eax
	; Pido para el NGde
	push	dword		8
	call	malloc
	add		esp,		4
	; Le informo cual es su tamaño y adonde tiene su numero (r)
	mov		dword		[eax],		tam
	mov		dword		[eax + 4],	edi
%endmacro

;-------------------------------------------------------------------


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	NGde* SumaMiniI(Ngde *sumando1, NGde *sumando2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SumaMiniI:
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; eax = ret
	; ebx = sumando1 (alto)
	; ecx = sumando2 (bajo)
	; edx = sumando2 (alto)
	; edi = ret->r
	; esi = sumando1 (bajo)
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
	SF_ini
	
	; Cargo los 2 sumandos de parametro y extiendo los valores de 4 a 8 bytes. Si metiese de parametro a la macro [ebp + ...] terminaria haciendo 
	; doble indireccion en algun momento, asique mejor asi
	mov		edx,	[ebp + 8]
	LevantarNGdeMini		eax,		edx
	cdq
	mov		esi,	eax
	mov		ebx,	edx
	mov		edx,	[ebp + 12]
	LevantarNGdeMini		eax,		edx
	cdq
	mov		ecx,	eax
	
	; Sumo la parte baja de los sumandos y la alta con carry, por si la suma de los bajos tiro un carry
	add		esi,	ecx
	adc		ebx,	edx
	
	; Creo el NGde de retorno (siempre de tamaño 8) y guardo el puntero en ecx
	NuevoNGde		8
	
	; Agrego las dos mitades del resultado
	mov		dword		[edi + 4],		esi
	mov		dword		[edi],			ebx
	
	SF_fin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	NGde* RestaNxDI(NGde *minuendo, NGde *sustraendo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RestaNxDI:
	SF_ini
	
	mov		ebx,		[ebp + 8]		; ebx -> minuendo
		
	; Creo el retorno con 4 bytes mas que el minuendo
	mov		esi,		[ebx]			; esi -> minuendo.tam
	add		esi,		4
	NuevoNGde			esi				; eax -> ret, edi = ret.r
		
	push 	eax							; Guardo el valor de retorno asi ahora lo puedo pisotear felizmente
	mov		ecx,		[ebx]			; recupero el minuendo.tam en ecx
	
	; Cargo el valor del sustraendo, total es de 4 bytes
	mov		esi,		[ebp + 12]		; esi -> sustraendo
	mov		edx,		[esi + 4]		; edx = sustraendo.r
	mov		edx,		[edx]			; edx = *(sustraendo.r)
	
	; Le resto el sustraendo al dword menos significativo del minuendo y ya voy guardando en ret
	mov		eax,		[ebx + 4]		; eax -> minuendo.r
	mov		esi,		[eax + ecx - 4]	; esi = LSdword del minuendo.r
	sub		esi,		edx				; esi = la resta de los dwords mas bajos
	mov		dword		[edi + ecx],		esi	; Guardo en el LSdword del ret.r, a este no le resto 4 porque tiene 4 bytes mas que el minuendo
	
	; Ahora voy a ir recorriendo todos los dwords restando los burrows que se pudieron haber formado
	; hasta que no tenga carry o me quede sin mas minuendo
	_bucle_burrow:
		dec		ecx									; Hago esta chanchada para no alterar el carry
		dec		ecx
		dec		ecx
		dec		ecx
		jz		_fin_bucle_burrow					; Si no tengo mas tamaño a quien pedirle, termine. En algun momento va a ser 0 porque minuendo.tam mod 4 = 0 y voy restando de a 4

		mov		esi,		[eax + ecx - 4]			; Cargo el dword del minuendo.r
		sbb		esi,		0						; Le resto solo el posible burrow (o carry)
		mov		dword		[edi + ecx],		esi	; Escribo en el ret.r
		
		jmp		_bucle_burrow
	_fin_bucle_burrow:
	
	; Por ultimo, tengo que decidir si los 4 bytes de sobra que tiene el ret son extendidos de positivo o negativo.
	cmp			dword		esi,		0
	jl			_neg
		_pos:
			mov			dword		[edi],		0x00000000
			jmp			_sig
		_neg:
			mov			dword		[edi],		0xFFFFFFFF
	_sig:
		
	pop		eax										; Recupero el puntero al ret que habia pisoteado felizmente
		
	SF_fin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Codigo en C para probar las funciones

#include <stdio.h>
#include <stdlib.h>

/* Hice que la estructura sea un tipo asi mejoraba la sintaxis, en el fondo son lo mismo */
typedef struct{int tam; int *r;} NGde;

/* Le juramos a C que vamos a definirle estas funciones afuera */
extern NGde* SumaMiniI(NGde *sumando1, NGde *sumando2);
extern NGde* RestaNxDI(NGde *minuendo, NGde *sustraendo);


/* Muestra un NGde por pantalla */
void MostrarNGde(const NGde n)
{
	/* Notar que como r es puntero a int hay que sumar solo 1 para avanzar un dword (sizeof(int) == 4) */
	int i = 0;
	while(i < n.tam)
	{
		printf("%p ", *(n.r + i / 4));
		i = i + 4;
	}
}


/************* Rutina de pruebas de la primer funcion *************/
void PruebasSumaMiniI()
{
	/* Declaro 4 NGdes para usar de ejemplo y 3 punteros que van a apuntar a sus sumas */
	NGde a;
	NGde b;
	NGde c;
	NGde d;
	NGde e;
	NGde *s1;
	NGde *s2;
	NGde *s3;
	
	/* Inicializo los 4 NGdes con algunos valores */
	a.tam = 4;
	a.r = malloc(a.tam);
	*(a.r) = 0xFFFFFFFF;
	printf("a.tam: %u, *(a.r): ", a.tam);
	MostrarNGde(a);
	printf("\n");
	
	b.tam = 1;
	b.r = malloc(b.tam);
	*(b.r) = 0x0B;
	printf("b.tam: %u, *(b.r): ", b.tam);
	MostrarNGde(b);
	printf("\n");
	
	c.tam = 2;
	c.r = malloc(c.tam);
	*(c.r) = 0x4513;
	printf("c.tam: %u, *(c.r): ", c.tam);
	MostrarNGde(c);
	printf("\n");
	
	d.tam = 2;
	d.r = malloc(d.tam);
	*(d.r) = 0xE320;
	printf("d.tam: %u, *(d.r): ", d.tam);
	MostrarNGde(d);
	printf("\n");
	
	e.tam = 4;
	e.r = malloc(e.tam);
	*(e.r) = 0xFFFFFFFF;
	printf("e.tam: %u, *(e.r): ", e.tam);
	MostrarNGde(e);
	printf("\n");
	
	
	/* Tres sumas de ejemplo */
	s1 = SumaMiniI(&a, &b);
	printf("s1->tam: %u, *(s1->r): ", s1->tam);
	MostrarNGde(*s1);
	printf("\n");
	
	s2 = SumaMiniI(&c, &d);
	printf("s2->tam: %u, *(s2->r): ", s2->tam);
	MostrarNGde(*s2);
	printf("\n");
	
	s3 = SumaMiniI(&e, &a);
	printf("s3->tam: %u, *(s3->r): ", s3->tam);
	MostrarNGde(*s3);
	printf("\n");
	
	
	/* Los leaks son mala onda */
	free(s1->r);	free(s2->r);	free(s1);	free(s2);
}


/************* Rutina de pruebas de la segunda funcion *************/
void PruebasRestaNxDI()
{
	/* Declaro 4 NGdes para usar de ejemplo y 3 punteros que van a apuntar a sus restas */
	NGde a;
	NGde b;
	NGde c;
	NGde d;
	NGde *r1;
	NGde *r2;
	NGde *r3;
	
	/* Inicializo los 4 NGdes con algunos valores */
	a.tam = 4;
	a.r = malloc(a.tam);
	*(a.r) = 0x00000100;
	printf("a.tam: %u, *(a.r): ", a.tam);
	MostrarNGde(a);
	printf("\n");
	
	b.tam = 4;
	b.r = malloc(b.tam);
	*(b.r) = 0x0000000A;
	printf("b.tam: %u, *(b.r): ", b.tam);
	MostrarNGde(b);
	printf("\n");
	
	c.tam = 12;
	c.r = malloc(c.tam);
	*(c.r) = 0xAE3490F1;
	*(c.r + 1) = 0xAE3490F1;
	*(c.r + 2) = 0xAE3490F1;
	printf("c.tam: %u, *(c.r): ", c.tam);
	MostrarNGde(c);
	printf("\n");
	
	d.tam = 32;
	d.r = malloc(d.tam);
	*(d.r) = 0;
	*(d.r + 1) = 0;
	*(d.r + 2) = 0;
	*(d.r + 3) = 0;
	*(d.r + 4) = 0;
	*(d.r + 5) = 0;
	*(d.r + 6) = 0;
	*(d.r + 7) = 0;
	printf("d.tam: %u, *(d.r): ", d.tam);
	MostrarNGde(d);
	printf("\n");
	
	/* Tres restas de ejemplo */
	r1 = RestaNxDI(&b, &a);
	printf("r1->tam: %u, *(r1->r): ", r1->tam);
	MostrarNGde(*r1);
	printf("\n");
	
	r2 = RestaNxDI(&c, &a);
	printf("r2->tam: %u, *(r2->r): ", r2->tam);
	MostrarNGde(*r2);
	printf("\n");
	
	r3 = RestaNxDI(&d, &a);
	printf("r3->tam: %u, *(r3->r): ", r3->tam);
	MostrarNGde(*r3);
	printf("\n");
	
	
	/* Los leaks son mala onda */
	free(r1->r);	free(r2->r);	free(r3->r);	free(r1);	free(r2);	free(r3);
}


/************* Punto de entrada ****************/
int main(int argc, char *argv[])
{
	printf(" .................. Pruebas de SumaMiniI .................. \n");
	PruebasSumaMiniI();
	printf("\n\n .................. Pruebas de RestaNxDI .................. \n");
	PruebasRestaNxDI();
	
	return 0;
}


Makefile para compilar los dos archivos

RM= rm
NASM = nasm

# optimization
#
OPT= -g -ggdb -O2

# flags for ANSI compiles
#
CFLAGS= -pedantic -ansi -Wall ${OPT}

# ANSI compiler
#
GCC= gcc

OBJ=main.o parcial.o
OTHEROBJ=
INCS=
MAIN=parcial

.PHONY: all win linux

all: 
	@echo Debe elegir alguno de los sistemas operativos \(win, linux\). Ejemplo:
	@echo   make linux

win:
	make NOPT="-fwin32 -Dwin32"  ${MAIN}

linux:
	make NOPT=-felf ${MAIN}

${MAIN}: ${OBJ} ${OTHEROBJ} $(INCS)
	${GCC} ${CFLAGS} -o ${MAIN} ${OBJ} ${OTHEROBJ}

%.o: %.asm 
	${NASM} ${NOPT} -O1 $< -o $@

%.o: %.c
	${GCC} ${CFLAGS} -c $< -o $@ 

clean:
	${RM} -f ${OBJ} ${OTHEROBJ} ${MAIN}

install: all
	${CAT} ${MAIN} > /dev/null

Notar que solo hay que poner "make win" o "make linux".


Ejercicio 2 (IA64)

a) signo

.proc signo
signo:
   alloc loc0 = ar.pfs,1,1,0,0
   
   cmp.eq p1,p2 = 0, in0
   (p1) mov r8 = 0
   (p2) cmp.gts.unc p3, p4 = 0, in0
   (p3) mov r8 = -1
   (p4) mov r8 = 1
   mov ar.pfs = loc0
   br.ret.sptk.many b0
.endp signo

b) Listas

.proc listas
listas:
    alloc loc0 = ar.pfs,5,3,1,0
    mov ar.lc = in4 // in4=N
    mov loc1 = b0 //guarda el branch
loop:
    ld8 loc2 = [in0], 8
    mov out0 = loc2
    br.call b0 = signo
    cmp.eq p1,p2 = 0, r8
    (p1) st8 [in3] = loc2, 8 // in3 = ceros
    (p2) cmp.gts.unc p3, p4 = 0, r8
    (p3) st8 [in2] = loc2, 8 // negativos
    (p4) st8 [in1] = loc2, 8 // positivos
    br.cloop loop
    
    st8 [in1] = r0
    st8 [in2] = r0
    st8 [in3] = -1
    
    mov b0 = loc1
    mov ar.pfs = loc0
    br.ret.sptk.many bo  //termina la locura


Para Patricia esto estaba bien, espero que lo este para uds.