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: | ||
== 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... | |||
por | ; 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.