Processing math: 100%

April 17, 2012

Tarea Intro.Lenguaje Ensamblador

Para esta tarea de cómputo integrado decidí hacer el sencillo programa de el Triángulo de Pascal, este programa lo realicé en C. El programa lo hice lo más sencillo que pude, para poder comprenderlo un poco mejor.

#include<stdio.h>
int main(){
int Nivel, i, j, k;
i = 0;
printf("Cuantos niveles deseas? ---> ");
scanf("%d", &Nivel);
int Ant[Nivel];
while(i < Nivel){
int Pasc[i + 1];
Pasc[0] = 1;
Pasc[i] = 1;
//SUMAS
if(i >= 2){
for(j = 1; j < i; j++){
Pasc[j] = Ant[j] + Ant[j-1];
}
}
for(j = 0; j < i+1; j++){
Ant[j] = Pasc[j];
}
printf("\n");
for(j = 0; j < i+1; j++){
printf("%d ", Pasc[j]);
}
printf("\n");
i++;
}
}
view raw Pascal.c hosted with ❤ by GitHub




Ensamblador.

Para obtener el código en ensamblador utilicé gcc, el cual utiliza as como ensamblador y por lo tanto utiliza la sintaxis AT&T, también se puede comprobar porque al comienzo de los registros va un %, lo cual es característico de AT&T.

Utilicé la siguiente instrucción para obtener el código en ensamblador:

gcc -S Pascal.c

Y esto fue lo que me arrojó:

.file "Pascal.c" ;archivo fuente de entrada
.section .rodata ;seccion de solo lectura.Se definen constantes y literales
.LC0: ;etiqueta
.string "Cuantos niveles deseas? ---> " ;cadena almacenada en este segmento
.LC1: ;etiqueta
.string "%d" ;string
.LC2: ;etiqueta
.string "%d " ;string
.text ;Seccion de mandos.En este punto comienzan las instrucciones.
.globl main ;declaracion de main como simbolo global
.type main, @function ;main como funcion
main: ;etiqueta funcion main.Indica inicio del programa principal
leal 4(%esp), %ecx ;Se almacena en %ecx el valor de 4+%esp.Puntero de la pila
andl $-16, %esp ;alinea la pila
pushl -4(%ecx) ;mueve el puntero de la pila
pushl %ebp ;inicializa la pila.
movl %esp, %ebp ;mueve contenido de %esp a %ebp (4 bytes)
pushl %edi ;se guarda %edi, porque se estara utilizando
pushl %esi ;se guarda %esi, porque se estara utilizando
pushl %ebx ;guarda %ebx en la pila
pushl %ecx ;guarda %ecx en la pila
subl $136, %esp ;reserva espacio
movl %gs:20, %eax ;mueve contenido en %gs:20 al tope de la pila.Checa la memoria
movl %eax, -28(%ebp) ;mueve %eax en el registro %ebp+28
xorl %eax, %eax ;%eax = 0;
movl %esp, %eax ;mueve contenido de %esp a %eax
movl %eax, %edi ;mueve contenido de %esp a %edi
movl $0, -36(%ebp) ;pone en 0 el registro %ebp+36
movl $.LC0, %eax ;string en la etiqueta LC0 se mueve al inicio de la pila
movl %eax, (%esp) ;se mueve la direccion de memoria %eax al tope de la pila
call printf ;llamada a printf
movl $.LC1, %edx ;mueve string a .LC1 a %edx
leal -32(%ebp), %eax ;actualiza %eax(registro de entrada y salida) con direccion de -32(%ebp)
movl %eax, 4(%esp) ;mueve contenido de %eax a %esp+4
movl %edx, (%esp) ;mueve contenido de %eax al cual apunta %esp(tope de la pila)
call __isoc99_scanf ;llamada a scanf
movl -32(%ebp), %ecx ;mueve contenido de la direccion 32 de %ebp en %ecx
leal -1(%ecx), %eax ;carga direccion efectiva de -1 de %ecx a %eax
movl %eax, -48(%ebp) ;mueve contenido de %eax en la direccion 48 de %ebp
movl %ecx, %eax ;%ecx apunta a %eax
movl $0, %edx ;actualiza %edx en 0
movl %eax, %ebx ;eax apunta a %ebx
andb 255, %bh ;AND entre la direccion 255 y %esp
movl %edx, %esi ;mueve contenido de %edx a %esi
andl 15, %esi ;AND entre la direccion 15 y %esi
movl %ebx, %eax ;carga contenido de %ebx a %eax
movl %esi, %edx ;mueve contenido de %esi a %edx
shldl $5, %eax, %edx ;se desplaza 5 posiciones a la izquierda en los registros %eax y %edx
sall $5, %eax ;se desplaza a la izquierda 5 posiciones en el registro %eax
movl %eax, %ebx ;%eax apunta a %ebx
andb 255, %bh ;AND entre la direccion 255 y %bh
movl %ebx, -80(%ebp) ;copia contenido de %eax en la posicion -80 del registro %ebp
movl %edx, %ebx ;carga contenido de %edx en %ebx
andl 15, %ebx ;AND entre la direccion 15 y %ebx
movl %ebx, -76(%ebp) ;mueve contenido de %ebx a la posicion -76 del registro %ebp
movl -80(%ebp), %eax ;mueve contenido de la posicion -80 de %ebp a %eax
movl -76(%ebp), %edx ;mueve contenido de posicion -76 en %ebp en edx
movl %ecx, %eax ;mueve contenido de %ecx a %eax
movl $0, %edx ;actualiza %edx en 0
movl %eax, %ebx ;%eax apunta a %ebx
andb $255, %bh ;AND entre la direccion %255 y %bh
movl %ebx, -88(%ebp)
movl %edx, %ebx ;carga contenido de %edx en %ebx
andl $15, %ebx ;AND entre la direccion %15 y %ebx
movl %ebx, -84(%ebp) ;mueve contenido de %ebp en la posicion -84 de %ebp
movl -88(%ebp), %eax
movl -84(%ebp), %edx ;copia contenido de posicion -84 de %eax en %edx
shldl $5, %eax, %edx ;se desplaza a la izquierda 5 posiciones en el registro %edx
sall $5, %eax ;se desplaza a la izquierda 5 posiciones en el registro %eax
movl %eax, %ebx ;copia contenido de %eax a %ebx
andb 255, %bh ;AND entre la direccion 255 y el registro %bh
movl %ebx, -96(%ebp)
movl %edx, %ebx ;mueve contenido de %edx a %ebx
andl 15, %ebx ;AND entre la direccion 15 y el registro %ebx
movl %ebx, -92(%ebp)
movl -96(%ebp), %eax ;copia contenido de posicion -96 de %ebp en %eax
movl -92(%ebp), %edx
movl %ecx, %eax ;mueve contenido de %ecx a %eax
sall $2, %eax ;se desplaza a la izquierda 2 posiciones en el registro %eax
addl $15, %eax ;%eax = %eax + 15
addl $15, %eax ;%eax = %eax + 15
shrl $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
sall $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
subl %eax, %esp ;%esp = %esp - %eax
leal 8(%esp), %eax ;carga direccion efectiva de posicion 8 de %esp a %eax
addl $15, %eax ;%eax = %eax + 15
shrl $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
sall $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
movl %eax, -52(%ebp) ;mueve contenido de %eax en la posicion -52 de %ebp
jmp .L2 ;salto incondicional a la etiqueta .L2
.L10:
movl %esp, %eax ;copia contenido de %esp en %eax
movl %eax, %esi ;mueve contenido de %eax a %esi
movl -36(%ebp), %eax ;copia contenido de posicion -36 de %ebp en %eax
leal 1(%eax), %ecx ;carga direccion efectiva de 1 de %eax a %ecx
leal -1(%ecx), %eax ;carga direccion efectiva de -1 de %ecx a %eax
movl %eax, -56(%ebp)
movl %ecx, %eax ;copia contenido de %ecx a %eax
movl $0, %edx ;pone en 0 el contenido del registro %edx
movl %eax, %ebx ;ecx apunta a %eax
andb 255, %bh ;AND entre 255 y conetenido de %bh
movl %ebx, -104(%ebp)
movl %edx, %ebx ;mueve contenido de %edx a %ebx
andl 15, %ebx ;AND entre el direccion 15 y registro %ebx
movl %ebx, -100(%ebp)
movl -104(%ebp), %eax ;copia contenido de posicion -104 %ebp en %eax
movl -100(%ebp), %edx
shldl $5, %eax, %edx ;se desplaza a la izquierda 5 posiciones en el registro %eax y %edx
sall $5, %eax ;se desplaza a la izquierda 5 posiciones en el registro %eax
movl %eax, %ebx ;%ecx apunta a %ebx
andb 255, %bh ;AND entre direccion 255 y registro %bh
movl %ebx, -112(%ebp)
movl %edx, %ebx ;mueve contenido de %edx a %ebx
andl 15, %ebx ;AND entre direccion 15 y registro %ebx
movl %ebx, -108(%ebp)
movl -112(%ebp), %eax ;copia contenido en posicion -112 de %eax en %eax
movl -108(%ebp), %edx
movl %ecx, %eax ;mueve contenido de %ecx a %eax
movl $0, %edx ;pone en 0 el registro %ebx
movl %eax, %ebx ;copia contenido de %eax a %ebx
andb 255, %bh ;AND entre 255 y %bh
movl %ebx, -120(%ebp)
movl %edx, %ebx ;mueve contenido de %ecx a %ebx
andl 15, %ebx ;AND entre 15 y %ebx
movl %ebx, -116(%ebp)
movl -120(%ebp), %eax ;copia contenido en posicion -120 de %ebp en %eax
movl -116(%ebp), %edx
shldl $5, %eax, %edx ;se desplaza a la izquierda 5 posiciones en el registro %eax y %edx
sall $5, %eax ;se desplaza a la izquierda 5 posiciones en el registro %eax
movl %eax, %ebx ;mueve contenido de %eax a %ebx
andb 255, %bh ;AND entre direccion 255 y registro %bh
movl %ebx, -128(%ebp)
movl %edx, %ebx ;mueve contenido de %edx a %ebx
andl 15, %ebx ;AND entre direccion 15 y %ebx
movl %ebx, -124(%ebp)
movl -128(%ebp), %eax ;copia contenido de posicion -128 de %ebp en %eax
movl -124(%ebp), %edx
movl %ecx, %eax ;apunta %ecx apunta a %eax
sall $2, %eax ;se desplaza a la izquierda 2 posiciones en el registro %eax
addl $15, %eax ;%eax = %eax + registro 15
addl $15, %eax ;%eax = %eax + registro 15
shrl $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
sall $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
subl %eax, %esp ;%esp = %esp - %eax
leal 8(%esp), %eax ;carga direccion efectiva de 8 de %esp a %eax
addl $15, %eax ;%eax = %eax + 15
shrl $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
sall $4, %eax ;se desplaza a la izquierda 4 posiciones en el registro %eax
movl %eax, -60(%ebp)
movl -60(%ebp), %eax ;copia contenido de posicion -60 de %ebp en %eax
movl 1, (%eax) ;copia direccion 1 en el registro %eax
movl -36(%ebp), %edx
movl -60(%ebp), %eax
movl 1, (%eax,%edx,4) ;mueve contenido de direccion 1 en %eax y %edx
cmpl 1, -36(%ebp) ;compara registro 1 y posicion -36 de %ebp
jle .L3 ;salta si es menor o igual a, o mayor si no lo es
movl $1, -40(%ebp)
jmp .L4 ;salto incondicional a la etiqueta 4
.L5:
movl -40(%ebp), %ebx
movl -40(%ebp), %edx ;mueve contenido de posicion -40 de %ebp en %edx
movl -52(%ebp), %eax
movl (%eax,%edx,4), %ecx
movl -40(%ebp), %eax ;copia contenido de posicion -40 de %ebp en %eax
leal -1(%eax), %edx ;carga direccion efectiva de -1 de %eax a %edx
movl -52(%ebp), %eax ;mueve contenido de posicion -52 de %ebp en %eax
movl (%eax,%edx,4), %eax
leal (%ecx,%eax), %edx ;copia direccion efectiva de %ecx y %edx a %edx
movl -60(%ebp), %eax ;copia contenido de posicion -60 de %ebp en %eax
movl %edx, (%eax,%ebx,4)
addl 1, -40(%ebp) ;posicion -40 de %ebp + contenido registro 1
.L4:
movl -40(%ebp), %eax ;mueve contenido de posicion -40 de %ebp en %eax
cmpl -36(%ebp), %eax
jl .L5 ;si es menor o igual pasa a la etiqueta 5
.L3:
movl $0, -40(%ebp)
jmp .L6 ;salto incondicional a la etiqueta 6
.L7:
movl -40(%ebp), %ecx ;mueve contenido de posicion -40 de %ebp en %ecx
movl -40(%ebp), %edx
movl -60(%ebp), %eax ;copia contenido de posicion -60 de %ebp en %ecx
movl (%eax,%edx,4), %edx
movl -52(%ebp), %eax ;mueve contenido de posicion -52 de %ebp en %eax
movl %edx, (%eax,%ecx,4)
addl 1, -40(%ebp) ;posicion -40 de %ebp + registro 1
.L6:
movl -36(%ebp), %eax ;copia contenido de posicion -36 de %ebp en %eax
addl $1, %eax ;%eax = %eax + registro 1
cmpl -40(%ebp), %eax ;comparacion entre posicion -40 de %ebp y %eax
jg .L7 ;si es mas grande salta a etiqueta 7
movl $10, (%esp)
call putchar ;llamada a putchar
movl $0, -40(%ebp)
jmp .L8 ;salto incondicional a la etiqueta 8
.L9:
movl -40(%ebp), %edx ;mueve contenido de posicion -40 de %ebp en %edx
movl -60(%ebp), %eax
movl (%eax,%edx,4), %edx
movl $.LC2, %eax ;mueve contenido de la etiqueta .LC2 en %eax
movl %edx, 4(%esp)
movl %eax, (%esp) ;copia contenido de %eax en %esp
call printf ;llamada a printf
addl $1, -40(%ebp) ;libera el espaci ocupado por los argumentos
.L8:
movl -36(%ebp), %eax
addl $1, %eax ;%eax = %eax + registro 1
cmpl -40(%ebp), %eax
jg .L9 ;si es mas grande salta a etiqueta 9
movl $10, (%esp)
call putchar ;llamada a putchar
addl $1, -36(%ebp)
movl %esi, %esp
.L2:
movl -32(%ebp), %eax
cmpl %eax, -36(%ebp) ;comparacion entre %eax y posicion -36 de %ebp
jl .L10 ;si es menor o igual pasa a la etiqueta 10
movl %edi, %esp ;mueve contenido de %edi a %esp
movl -28(%ebp), %edx ;copia contenido de posicion -28 de %ebp en %edx
xorl %gs:20, %edx ;XOR entre %gs:20 y %edx
je .L12 ;si es igual o 0 salta a etiqueta 12.
call __stack_chk_fail ;comprueba la pila y aborta si esta da;ada
.L12:
leal -16(%ebp), %esp ;carga direccion efectiva de -16 de %ebp a %esp
addl $0, %esp ;%esp = %esp + 0
popl %ecx ;se carga un valor en %ecx
popl %ebx ;se carga un valor en %ebx
popl %esi ;se carga un valor en %esi
popl %edi ;se carga un valor en %edi
popl %ebp ;se carga un valor en %ebp
leal -4(%ecx), %esp ;carga direccion efectiva de -4 de %ecx a %esp
ret ;termina el programa
.size main, .-main ;parametros del SO. Indica los bytes que ocupa main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3"
.section .note.GNU-stack,"",@progbits
view raw Pascal.s hosted with ❤ by GitHub


Como podrán ver de un pequeño programa en c me arrojó 235 líneas de código (O.o). En las líneas pueden observar una pequeña explicación de lo que hace cada una.


Optimización del código
Para optimizar el código quité las líneas del comienzo que vienen siendo el nombre del programa (que la agrega gcc por default) y las de alineación de la pila; también eliminé las líneas que relacionadas con la arquitectura de 64 bits; así como también las líneas de función que no afectaba el funcionamiento del programa.

Aquí el código optimizado y como podrán observar el código pasó de 235 líneas a 120 O.o:

.section .rodata #seccion de solo lectura.Se definen constantes y literales
.LC0: #etiqueta
.string "Cuantos niveles deseas? ---> " #cadena almacenada en este segmento
.LC1: #etiqueta
.string "%d" #string
.LC2: #etiqueta
.string "%d " #string
.text #Seccion de mandos.En este punto comienzan las instrucciones.
.globl main #declaracion de main como simbolo global
.type main, @function #main como funcion
main: #etiqueta funcion main.Indica inicio del programa principal
leal 4(%esp), %ecx #Se almacena en %ecx el valor de 4+%esp.Puntero de la pila
movl %esp, %ebp #mueve contenido de %esp a %ebp (4 bytes)
pushl %edi #se guarda %edi, porque se estara utilizando
pushl %esi #se guarda %esi, porque se estara utilizando
pushl %ebx #guarda %ebx en la pila
pushl %ecx #guarda %ecx en la pila
subl $136, %esp #reserva espacio
movl %gs:20, %eax #mueve contenido en %gs:20 al tope de la pila.Checa la memoria
movl %eax, -28(%ebp) #mueve %eax en el registro %ebp+28
movl %esp, %eax #mueve contenido de %esp a %eax
movl %eax, %edi #mueve contenido de %esp a %edi
movl $0, -36(%ebp) #pone en 0 el registro %ebp+36
movl $.LC0, %eax #string en la etiqueta LC0 se mueve al inicio de la pila
movl %eax, (%esp) #se mueve la direccion de memoria %eax al tope de la pila
call printf #llamada a printf. Imprime String de etiqueta .LC0
movl $.LC1, %edx #mueve string a .LC1 a %edx
leal -32(%ebp), %eax #actualiza %eax(registro de entrada y salida) con direccion de -32(%ebp)
movl %eax, 4(%esp) #mueve contenido de %eax a %esp+4
movl %edx, (%esp) #mueve contenido de %eax al cual apunta %esp(tope de la pila)
call __isoc99_scanf #llamada a scanf. Lee la cantidad de niveles
movl %ecx, %eax #mueve contenido de %ecx a %eax
sall $2, %eax #se desplaza a la izquierda 2 posiciones en el registro %eax
addl $15, %eax #%eax = %eax + 15
addl $15, %eax #%eax = %eax + 15
subl %eax, %esp #%esp = %esp - %eax
leal 8(%esp), %eax #carga direccion efectiva de posicion 8 de %esp a %eax
shrl $4, %eax #se desplaza a la izquierda 4 posiciones en el registro %eax
sall $4, %eax #se desplaza a la izquierda 4 posiciones en el registro %eax
movl %eax, -52(%ebp) #mueve contenido de %eax en la posicion -52 de %ebp
.L10:
movl %esp, %eax #copia contenido de %esp en %eax
movl %eax, %esi #mueve contenido de %eax a %esi
movl -36(%ebp), %eax #copia contenido de posicion -36 de %ebp en %eax
movl -124(%ebp), %edx
sall $2, %eax #se desplaza a la izquierda 2 posiciones en el registro %eax
addl $15, %eax #%eax = %eax + registro 15
addl $15, %eax #%eax = %eax + registro 15
subl %eax, %esp #%esp = %esp - %eax
leal 8(%esp), %eax #carga direccion efectiva de 8 de %esp a %eax
addl $15, %eax #%eax = %eax + 15
movl %eax, -60(%ebp)
movl 1, (%eax) #copia direccion 1 en el registro %eax
movl -36(%ebp), %edx
cmpl 1, -36(%ebp) #compara registro 1 y posicion -36 de %ebp
jle .L3 #salta si es menor o igual a, o mayor si no lo es
movl $1, -40(%ebp)
.L5:
movl -40(%ebp), %ebx
movl -40(%ebp), %edx #mueve contenido de posicion -40 de %ebp en %edx
movl -52(%ebp), %eax
movl (%eax,%edx,4), %ecx
movl -40(%ebp), %eax #copia contenido de posicion -40 de %ebp en %eax
leal -1(%eax), %edx #carga direccion efectiva de -1 de %eax a %edx
movl -52(%ebp), %eax #mueve contenido de posicion -52 de %ebp en %eax
movl (%eax,%edx,4), %eax
leal (%ecx,%eax), %edx #copia direccion efectiva de %ecx y %edx a %edx
movl -60(%ebp), %eax #copia contenido de posicion -60 de %ebp en %eax
movl %edx, (%eax,%ebx,4)
addl 1, -40(%ebp) #posicion -40 de %ebp + contenido registro 1
.L4:
movl -40(%ebp), %eax #mueve contenido de posicion -40 de %ebp en %eax
cmpl -36(%ebp), %eax
jl .L5 #si es menor o igual pasa a la etiqueta 5
.L3:
movl $0, -40(%ebp)
.L7:
movl -40(%ebp), %ecx #mueve contenido de posicion -40 de %ebp en %ecx
movl -40(%ebp), %edx
movl -60(%ebp), %eax #copia contenido de posicion -60 de %ebp en %ecx
movl (%eax,%edx,4), %edx
movl -52(%ebp), %eax #mueve contenido de posicion -52 de %ebp en %eax
movl %edx, (%eax,%ecx,4)
addl 1, -40(%ebp) #posicion -40 de %ebp + registro 1
.L6:
movl -36(%ebp), %eax #copia contenido de posicion -36 de %ebp en %eax
addl $1, %eax #%eax = %eax + registro 1
cmpl -40(%ebp), %eax #comparacion entre posicion -40 de %ebp y %eax
jg .L7 #si es mas grande salta a etiqueta 7
movl $10, (%esp)
call putchar #llamada a putchar.Imprime renglones en blanco
movl $0, -40(%ebp)
.L9:
movl -40(%ebp), %edx #mueve contenido de posicion -40 de %ebp en %edx
movl -60(%ebp), %eax
movl (%eax,%edx,4), %edx
movl $.LC2, %eax #mueve contenido de la etiqueta .LC2 en %eax
movl %edx, 4(%esp)
movl %eax, (%esp) #copia contenido de %eax en %esp
call printf #llamada a printf. Imprime los numeros
addl $1, -40(%ebp) #libera el espacio ocupado por los argumentos
.L8:
movl -36(%ebp), %eax
cmpl -40(%ebp), %eax
jg .L9 #si es mas grande salta a etiqueta 9
movl $10, (%esp)
call putchar #llamada a putchar.Imprime renglones en blanco
addl $1, -36(%ebp)
movl %esi, %esp
.L2:
movl -32(%ebp), %eax
cmpl %eax, -36(%ebp) #comparacion entre %eax y posicion -36 de %ebp
jl .L10 #si es menor o igual pasa a la etiqueta 10
movl -28(%ebp), %edx #copia contenido de posicion -28 de %ebp en %edx
je .L12 #si es igual o 0 salta a etiqueta 12.
.L12:
leal -16(%ebp), %esp #carga direccion efectiva de -16 de %ebp a %esp
popl %ecx #se carga un valor en %ecx
leal -4(%ecx), %esp #carga direccion efectiva de -4 de %ecx a %esp
ret #termina el programa
view raw Pascal.s hosted with ❤ by GitHub


Para comprobar que el código sigue funcionando igual que en C, lo que hice fue lo siguiente:

gcc Pascal.s -o Pascal.out

./Pascal.out

Y aquí el programa corriendo



Fuentes.
learnassembler
pdf

1 comment: