El
lenguaje ensamblador es un lenguaje que provee a la computadora o a
algún otro dispositivo una secuencia de instrucciones dado por una
secuencia de códigos binarios.Los programas que se hacen en ensamblador
tienden a tener una mayor velocidad y a consumir menos recursos que el
programa compilado desde otro lenguaje. El tiempo que tarda en
ejecutarse una rutina disminuye, y el espacio que ocupa es menor.
Por
otro lado, un programa escrito en lenguaje ensamblador es mucho más
complejo y dificil de crear y leer. A continuación se mostrará un simple hola mundo creado en lenguaje C y después ese mismo programa será
traducido en lenguaje ensamblador para hacer una comparación y entender un poco mejor las instrucciones que se muestran en el lenguaje ensamblador. Este programa simple nos servirá para ver las funciones básicas que se requieren en un programa escrito en ensamblador.
Este es un Hola mundo escrito en C:
Este es un Hola mundo escrito en C:
#includeint main() { printf("Hola mundo"); }
Para que este programa se pueda traducir a ensamblador se necesita seguir los siguientes pasos:
1. Se compila el programa:
gcc hola.c
2. Se corre el programa:
./a.out
3.
Se crea un ejecutable en ensablador. Esto se hará con -S después de gcc:
gcc -S hola.c
4. Ahora estará un archivo con el mismo nombre pero con terminación .s :
hola.s
Este programa se puede abrir en cualquir editor de texto (emacs) y se va a mostrar en lenguaje ensamblador.
Este es el código que se mostró:
.file "hola.c" #especifica el nombre del archivo original .section .rodata #contiene información de solo lectura del programa inicializado. .LC0: .string "Hola mundo" #se especifica el texto que se va a imprimir. .text #agrega el código a la sección de texto del programa .globl main #indica que main es global. .type main, @function main: #aqui empieza a correr el main pushl %ebp //push local a ebp movl %esp, %ebp #move local a esp y ebp andl $-16, %esp #alinea la pila subl $16, %esp #resta 16 bytes movl $.LC0, %eax #move la cadena a la parte superior de la pila movl %eax, (%esp) #move local a eax y esp call printf #aqui llama a la función printf. leave ret #return .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" .section .note.GNU-stack,"",@progbits
Aqui podemos observar que el programa es mucho más largo y contiene más instrucciones que el programa escrito en lenguaje C.
Después pude reducir la cantidad de líneas de código del programa y así quedo:
.file "hola.c" .LC0: .string "Hola mundo" .text .globl main main: pushl %ebp movl %esp, %ebp movl $.LC0, %eax movl %eax, (%esp) call printf leave
El programa todavía corre y ejecuta las mismas acciones que el programa original, y las líneas de código se reducieron un 40%.
Para poder ejecutar este programa y saber que funciona tenemos que seguir los siguientes pasos:
1. Crear el archivo ejecutable a partir del archivo .s:
gcc -o hola.exe hola.s
2. Se ejecuta el archivo .exe:
./hola.exe
Ahora el programa se va a ejecutar en la terminal. Con esto podemos modificar el código en ensamblador y verificar si todavía funciona.
Ahora hice un programa que genera palindromos de diferentes frases que escriba el usuario.
Este es el programa en C:
#includevoid inverso (const char * const ptrS ); //prototipo int main() { char enunciado [ 80 ]; //crea un arreglo de caracteres printf("Escribe una frase: \n"); gets( enunciado ); printf("La frase al revez es: \n"); inverso(enunciado ); printf("\n"); return 0; } void inverso (const char * const ptrS) { //si es el final de la cadena if (ptrS[ 0 ] == '\0' ){ return; } else { inverso( &ptrS[ 1 ] ); putchar( ptrS[ 0 ] ); } }
Este es el programa generado en ensamblador:
.LC0: .string "Escribe una frase: " #se especifica el texto que se va a imprimir. .LC1: .string "La frase al revez es: " #otro string .text #agrega el codigo a la seccion de texto del programa .globl main #indica que la funcion main es global .type main, @function main: #aqui empieza a correr el main .LFB0: .cfi_startproc pushl %ebp #se respalda el %ebp anterior .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp #move local a esp .cfi_def_cfa_register 5 andl $-16, %esp subl $112, %esp movl %gs:20, %eax movl %eax, 108(%esp) xorl %eax, %eax movl $.LC0, (%esp) call puts #llama a puts leal 28(%esp), %eax movl %eax, (%esp) call gets #llama a gets movl $.LC1, (%esp) call puts leal 28(%esp), %eax movl %eax, (%esp) call inverso movl $10, (%esp) call putchar movl $0, %eax movl 108(%esp), %edx xorl %gs:20, %edx je .L2 call __stack_chk_fail .L2: leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc LFE0: .size main, .-main .globl inverso .type inverso, @function inverso: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $24, %esp movl 8(%ebp), %eax movzbl (%eax), %eax testb %al, %al je .L6 .L4: movl 8(%ebp), %eax addl $1, %eax movl %eax, (%esp) call inverso movl 8(%ebp), %eax movzbl (%eax), %eax movsbl %al, %eax movl %eax, (%esp) call putchar jmp .L3 .L6: nop .L3: leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE1: .size inverso, .-inverso .ident"GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1" .section.note.GNU-stack,"",@progbits
Después pude reducir la cantidad de líneas de código del programa y así quedo:
.globl main #indica que la funcion main es global .LC0: .string "Escribe una frase: " #se especifica el texto que se va a imprimir. .LC1: .string "La frase al revez es: " #string .text #inicia la seccion de codigo .globl main #indica que la funcion main es global main: #indica que empieza el main .LFB0: .cfi_startproc pushl %ebp #se respalda el %ebp anterior movl %esp, %ebp #move local a esp movl %gs:20, %eax movl %eax, 108(%esp) movl $.LC0, (%esp) call puts #llama a puts leal 28(%esp), %eax movl %eax, (%esp) call gets #llama a gets movl $.LC1, (%esp) call puts #llama a puts leal 28(%esp), %eax movl %eax, (%esp) call inverso #llama a inverso movl $10, (%esp) call putchar #llama a putchar movl 108(%esp), %edx xorl %gs:20, %edx je .L2 .L2: leave ret .cfi_endproc .type inverso, @function inverso: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp subl $24, %esp movzbl (%eax), %eax testb %al, %al je .L6 .L4: movl 8(%ebp), %eax addl $1, %eax movl %eax, (%esp) call inverso movl 8(%ebp), %eax movzbl (%eax), %eax movl %eax, (%esp) call putchar jmp .L3 .L6: nop .L3: leave .cfi_endproc .LFE1:
Bibliografía
10 y 10
ResponderEliminar