lunes, 27 de febrero de 2012

Entrega 1 Lenguaje Ensamblador

El lenguaje Ensamblador o assembler es un lenguaje de programacion de bajo nivel el cual es utilizado para la programacion de computadoras,microprocesadores,microcontroladores ademas de muchos otros circuitos integrados. Se utiliza una representacion binaria tambien conocida como lenguaje maquina.

Programa generador de una matriz en C
El programa con el cual trabajare es un programa en lenguaje c que nos crea e imprime una matriz de NxM, el codigo es el siguiente.

#include<stdio.h>
/*Matriz lectura y impresion n x m*/
main()
{
int i,j,n,m;
printf("Dame el numero de filas:");
scanf("%d",&n);
printf("Dame el numero de columnas:");
scanf("%d",&m);
int A[n][m];
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("A[%d][%d]= ",i+1,j+1);
scanf("%d",&A[i][j]);
}
}
printf("\n\n");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d",A[i][j]);
}
printf("\n\n");
}
getch();
}
view raw Matriz.c hosted with ❤ by GitHub


Creamos el codigo ensamblador apartir del archivo.c utilizando lo siguiente.



Compilamos el codigo de ensamblador, en este caso aparece un error por el use del getch, basta con retirarlo para poder compilar y posteriormente poder crear el ejecutable.



Programa Convertido a Lenguaje Ensamblador
El codigo ensamblador generado es el siguiente, como podemos ver es un codigo bastante extenso ya que de 31 lineas de codigo paso a convertise en un codigo de 170 lineas.

.file "matriz.c"
.section .rodata
.LC0:
.string "Dame el numero de filas:"
.LC1:
.string "%d"
.LC2:
.string "Dame el numero de columnas:"
.LC3:
.string "A[%d][%d]= "
.LC4:
.string "\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %r13
pushq %r12
pushq %rbx
subq $72, %rsp
movq %rsp, %rax
movq %rax, %r12
.cfi_offset 3, -40
.cfi_offset 12, -32
.cfi_offset 13, -24
movl $.LC0, %eax
movq %rax, %rdi
movl $0, %eax
call printf
movl $.LC1, %eax
leaq -48(%rbp), %rdx
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
movl $.LC2, %eax
movq %rax, %rdi
movl $0, %eax
call printf
movl $.LC1, %eax
leaq -44(%rbp), %rdx
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
movl -44(%rbp), %ebx
movl -48(%rbp), %eax
movslq %ebx, %rdx
subq $1, %rdx
movq %rdx, -72(%rbp)
movslq %ebx, %rdx
leaq 0(,%rdx,4), %r13
movslq %eax, %rdx
subq $1, %rdx
movq %rdx, -64(%rbp)
movslq %ebx, %rdx
cltq
imulq %rdx, %rax
salq $2, %rax
leaq 15(%rax), %rdx
movl $16, %eax
subq $1, %rax
addq %rdx, %rax
movq $16, -88(%rbp)
movl $0, %edx
divq -88(%rbp)
imulq $16, %rax, %rax
subq %rax, %rsp
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
movq %rax, -56(%rbp)
movl $0, -40(%rbp)
jmp .L2
.L5:
movl $0, -36(%rbp)
jmp .L3
.L4:
movl -36(%rbp), %eax
leal 1(%rax), %edx
movl -40(%rbp), %eax
leal 1(%rax), %ecx
movl $.LC3, %eax
movl %ecx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
movq -56(%rbp), %rax
movl -40(%rbp), %edx
movslq %edx, %rcx
movslq %ebx, %rdx
imulq %rdx, %rcx
movl -36(%rbp), %edx
movslq %edx, %rdx
addq %rcx, %rdx
salq $2, %rdx
addq %rax, %rdx
movl $.LC1, %eax
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
addl $1, -36(%rbp)
.L3:
movl -44(%rbp), %eax
cmpl %eax, -36(%rbp)
jl .L4
addl $1, -40(%rbp)
.L2:
movl -48(%rbp), %eax
cmpl %eax, -40(%rbp)
jl .L5
movl $.LC4, %edi
call puts
movl $0, -40(%rbp)
jmp .L6
.L9:
movl $0, -36(%rbp)
jmp .L7
.L8:
movq %r13, %rsi
shrq $2, %rsi
movq -56(%rbp), %rax
movl -36(%rbp), %edx
movslq %edx, %rcx
movl -40(%rbp), %edx
movslq %edx, %rdx
imulq %rsi, %rdx
addq %rcx, %rdx
movl (%rax,%rdx,4), %edx
movl $.LC1, %eax
movl %edx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
addl $1, -36(%rbp)
.L7:
movl -44(%rbp), %eax
cmpl %eax, -36(%rbp)
jl .L8
movl $.LC4, %edi
call puts
addl $1, -40(%rbp)
.L6:
movl -48(%rbp), %eax
cmpl %eax, -40(%rbp)
jl .L9
movl $0, %eax
call getch
movq %r12, %rsp
leaq -24(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
.section .note.GNU-stack,"",@progbits
view raw Matriz.asm hosted with ❤ by GitHub


Explicación de algunas lineas:

SEGMENT y ENDS: Definen los segmentos a utilizar.
cfi_startproc:Se utiliza antes de cualquier función que tenga alguna entrada de datos.
Call:Llama a alguna acción próxima a realizarse


Programa de matriz en ensamblador optimizado
Despues de una larga revision de las cosas que eran realmente necesarias y las cuales no lo eran se lograron eliminar 54 lineas de codigo terminando con el siguiente codigo mas limpio y corto.

.file "matriz.c"
.section .rodata
.LC0:
.string "Dame el numero de filas:"
.LC1:
.string "%d"
.LC2:
.string "Dame el numero de columnas:"
.LC3:
.string "A[%d][%d]= "
.LC4:
.string "\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
movq %rsp, %rbp
subq $72, %rsp
movl $.LC0, %eax
movq %rax, %rdi
movl $0, %eax
call printf
movl $.LC1, %eax
leaq -48(%rbp), %rdx
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
movl $.LC2, %eax
movq %rax, %rdi
movl $0, %eax
call printf
movl $.LC1, %eax
leaq -44(%rbp), %rdx
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
movslq %ebx, %rdx
leaq 0(,%rdx,4), %r13
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
movq %rax, -56(%rbp)
movl $0, -40(%rbp)
.L5:
movl $0, -36(%rbp)
.L4:
movl -36(%rbp), %eax
leal 1(%rax), %edx
movl -40(%rbp), %eax
leal 1(%rax), %ecx
movl $.LC3, %eax
movl %ecx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
movq -56(%rbp), %rax
movslq %ebx, %rdx
imulq %rdx, %rcx
movl -36(%rbp), %edx
salq $2, %rdx
addq %rax, %rdx
movl $.LC1, %eax
movq %rdx, %rsi
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf
addl $1, -36(%rbp)
.L3:
movl -44(%rbp), %eax
cmpl %eax, -36(%rbp)
jl .L4
addl $1, -40(%rbp)
.L2:
cmpl %eax, -40(%rbp)
jl .L5
movl $.LC4, %edi
call puts
movl $0, -40(%rbp)
.L9:
movl $0, -36(%rbp)
.L8:
movq %r13, %rsi
shrq $2, %rsi
movq -56(%rbp), %rax
movl -36(%rbp), %edx
movslq %edx, %rcx
imulq %rsi, %rdx
movl (%rax,%rdx,4), %edx
movl $.LC1, %eax
movl %edx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
addl $1, -36(%rbp)
.L7:
movl -44(%rbp), %eax
cmpl %eax, -36(%rbp)
jl .L8
movl $.LC4, %edi
call puts
addl $1, -40(%rbp)
.L6:
cmpl %eax, -40(%rbp)
jl .L9
leaq -24(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %rbp
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
.section .note.GNU-stack,"",@progbits
view raw MatrizOpt.asm hosted with ❤ by GitHub


Por ultimo podemos ver que el programa despues de ser optimizado ejecuta de la misma forma que antes.


Referencias:
http://es.kioskea.net/faq/3284-compilar-un-programa-ensamblador-con-nasm
http://iie.fing.edu.uy/~vagonbar/gcc-make/gcc.htm

1 comentario:

  1. Esa getch() al final es una sonsera windows para que no cierre el terminal al terminar de ejecutar. No me quedo enteramente convencida que sepas el significado de cada línea de assembler generado... Te voy a poner 8 por el programa y 8 por el reporte por ahora; si quieres más, puedes mejorar el reporte, agregado algo de explicación del assembler o presentarlo bien en persona.

    ResponderEliminar