Cargando



Primeros pasos con Assembly

En este tutorial veremos de qué va el lenguaje Assembly, que necesitamos para empezar a utilizar el mismo y realizaremos algunos ejemplos básicos en ambas arquitecturas.


feb 22 2015 23:55
Profesional
feb 23 2015 10:11
Assembly es un lenguaje de bajo nivel cuya función es proporcionar todos los elementos necesarios para la programación de la arquitectura de PCs de escritorio o laptops. Su curva de aprendizaje es un poco elevada y muy pocos conceptos pueden ser aplicados de lenguajes de alto nivel como Python, Ruby o Java, sin embargo es el lenguaje más potente para la programación de arquitecturas en base a x64.

A pesar de ser un lenguaje complejo, en sus versiones más actuales deja de un lado el uso de hexadecimales y los reemplaza con convenciones de nombres más sencillas de recordar y leer, además que tiene características más elevadas como permitir el uso de macros y la inclusión de tipos de datos definidos por el usuario.

Cuando el proceso de desarrollo termina, estas líneas de código son leídas por el programa ensamblador y luego son traducidas a código de máquina por un proceso similar a la compilación en lenguajes de alto nivel pero que aquí es llamado ensamblar.

Para efectos de este tutorial estaremos viendo en primera instancia como es el proceso de codificación en 32 bits, ya que es un paso fundamental para lograr un entendimiento mayor del lenguaje y del proceso de codificación en aplicaciones de 64 bits, esto por compartir muchas características con la arquitectura x86 de 64 bits.

¿Qué necesitamos para comenzar?


Hay muchas formas de empezar a codificar Assembly para aplicaciones de 32 bits pero una de las formas más fáciles y prácticas de hacerlo es mediante Visual Studio ya que posee algo llamado ensamblado en línea donde el código de Assembly es embebido en C++ normal y corriente, esto lo podemos hacer en una sola línea o en bloques de código con la palabra reservada __asm.

Importante
La palabra reservada __asm puede ser utilizada con un solo underscore. Esto es una directiva antigua utilizada para garantizar la compatibilidad en aplicaciones no tan modernas.

Aclarado esto lo primero que debemos hacer es obtener Visual Studio, para este tutorial se utilizó la versión Express sin embargo el código es válido en ambas versiones del IDE. Descargamos en el siguiente enlace nuestro IDE y ejecutamos en el instalador:


assembly-primeros-pasos.jpg



Luego que el proceso de instalación finaliza ya podemos empezar a codificar en Assembly, para ello haremos un pequeño ejemplo donde demostraremos como podemos embeber el código de Assembly en C++ con la palabra reservada __asm, donde cualquier segmento de código al lado de esta palabra será tratado como código nativo de Assembly por el compilador de C++.

Ensamblado en línea


Abrimos nuestro Visual Studio y creamos un nuevo proyecto de tipo Win32 Console Application, presionamos Ok y se nos desplegará una el asistente de creación de proyecto el cual nos preguntará que tipo de proyecto queremos y si deseamos uno vacío, recomendamos dejar todas las opciones por defecto y presionar Finalizar:



El asistente nos creará un código base para nuestro proyecto, el cuál contendrá una librería y el método principal, este debe lucir de la siguiente forma:
#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){ return 0;}
Al tener el código base ahora necesitamos agregar nuestra línea de Assembly, adicionalmente debemos agregar la librería <iostream> para poder imprimir por consola y el namespace para que todo funcione correctamente, veamos el código final:
#include "stdafx.h"#include <iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){ int x = 0; _asm mov x, 25 cout<<"El valor para x es: "<<x<<endl; return 0;}
Lo que hemos hecho acá es definir una variable llamada x y luego mediante código Assembly le asignamos el valor de 25, para finalmente imprimirla con cout, como vemos es un proceso bastante sencillo embeber el código de Assembly, ahora solo nos falta ejecutar nuestro pequeño programa, para ello podemos presionar Ctrl + F5 donde se compilará y se ejecutará nuestro programa, veamos como luce esta operación:




Adicionalmente podemos incluir múltiples líneas de código de Assembly en nuestro código de C++, lo cual podemos lograr al colocar la palabra reservada __asm y abriendo un bloque de código, veamos como logramos esto:
float Sqrt(float f) { __asm {fld f // Coloca f en la pila de operacionesfsqrt // Calcula sqrt }}
Ventajas del ensamblado en línea
Existen muchos beneficios del usar el ensamblado en línea en vez de una aplicación nativa de 32 bits de Assembly, por ejemplo el envío de parámetros a las funciones es manejado completamente por el compilador de C++ y el mismo inyectará la cantidad de exacta de código de máquina por lo que no debemos preocuparnos por un desbordamiento de memoria ni nada por el estilo.


Pero así como tenemos ventajas también nos encontramos con desventajas de esta forma de codificar, una de ellas es que el desarrollador pierde un poco el control sobre la aplicación como por ejemplo, manipular la pila o incluso definir sus propias convenciones.

Ensamblado nativo en C++


El ensamblado en línea ofrece mucha flexibilidad y nos permite incursionar en este mundo de manera rápida y sencilla pero este método de codificación impide a los desarrolladores a acceder a algunos elementos de Assembly, por esta razón es común añadir código nativo y separado a nuestro proyecto.

Para ello necesitamos crear nuestros archivos por separado y luego incluir los métodos que necesitamos, para lograr nuestro objetivo vamos a seguir los siguientes pasos:

1- Primero creamos un nuevo proyecto, puede ser un proyecto de tipo C++ o de aplicación de Windows, ambos funcionan para añadir los archivos de Assembly.

2- Añadimos un archivo C++ a nuestro proyecto que llamaremos principal.cpp el cuál se encargará de llamar a un procedimiento de nuestro archivo Assembly enviándole un arreglo de valores numéricos y luego imprimiendo lo que retorne este procedimiento, veamos el contenido de nuestro archivo principal.cpp:
#include <iostream>using namespace std;extern "C" int encontrarNumMenor(int* i, int count);int main() { int arr[] = { 4, 2, 6, 4, 5, 1, 8, 9, 5, -5 }; cout << "El numero mas pequeño es: " << encontrarNumMenor(arr, 10) << endl; cin.get(); return 0;}
3- Luego hacemos click derecho en nuestro proyecto, el mismo se encuentra en la parte derecha de nuestra interfaz, en la sección de Solution Explorer. Seleccionamos la Build Dependencies y luego Build Customizations. Esto lo hacemos para establecer como Visual Studio manejará los archivos con extensión .asm, ya que no queremos el compilador de C++ compile estos archivos, nuestro objetivo es que VS le proporcione estos archivos a MASM para que los ensamble y luego estos archivos enlazados a nuestro C++ serán los encargados de formar el ejecutable final.

4- Para finalizar con las dependencias seleccionamos la opción de masm como podemos ver en la siguiente imagen:




Es importante realizar este paso antes de añadir cualquier archivo con código de Assembly ya que Visual Studio asigna lo que un archivo necesita hacer cuando es creado y no cuando es construido.

5- Luego necesitamos agregar otro archivo C++, pero esta vez con la extensión .asm, para este tutorial lo he llamado ensamblador.asm. De igual manera podemos colocarle cualquier nombre al mismo excepto main.asm ya que el compilador puede tener problemas localizando donde se encuentra tu método principal.

6- Nuestro archivo ensamblador.asm se encargará de calcular de una serie de valores numéricos cual es el valor más pequeño entre estos y luego C++ se encargará de recibir el valor para procesarlo mediante cout, veamos el contenido de nuestro archivo:
; ensamblador.asm.xmm.model flat, c.data.code encontrarNumMenor proc exportmov edx, dword ptr[esp + 4];mov ecx, dword ptr[esp + 8];mov eax, 7fffffffh;cmp ecx, 0;jle Finished;MainLoop:cmp dword ptr[edx], eax; cmovl eax, dword ptr[edx]; add edx, 4;dec ecx;jnz MainLoop;Finished:ret;encontrarNumMenor endpend
Esto nos permite separar nuestros archivos, así como nuestra lógica. La realización de este tipo de procedimientos en base a 32 bits es muy poco utilizado pero es importante conocer todas sus implicaciones, veamos ahora como cambiamos nuestro código para una aplicación de 64 bits así como los pasos que necesitamos realizar para adecuar nuestro entorno de Visual Studio.

Adecuando nuestra aplicación para x64


Visual Studio incluye todas las herramientas necesarias para añadir el ensamblado nativo a nuestro proyecto en C++, pero para trabajar en base a 64 bits necesitamos realizar algunas configuraciones adicionales a nuestro proyecto, veamos:

1- Los pasos para realizar este tipo de codificación son similares a nuestro ejemplo anterior, pero para adecuar VS nos dirigimos a la opción Build y seleccionamos Configuration Manager:


assembly-primeros-pasos-5.jpg



2- En la pantalla del gestor de configuración vamos a seleccionar la opción New o nuevo en la columna de plataforma, lo cual nos desplegará una segunda pantalla para seleccionar la plataforma del proyecto, seleccionamos x64 y en la opción Copy Settings From dejamos seleccionado la opción de Win32. Esto hará que VS cambie las rutas de la versión de 32 bits de MASM a la de 64, por lo que todo el trabajo lo hará el IDE.




3- Hecho esto ya podemos compilar nuestro código y ejecutarlo, sin embargo debemos modificar nuestro archivo Assembly ya que estamos trabajando sobre arquitecturas distintas, veamos el nuevo código para nuestro archivo:
; Listing: ensamblador.asm .code ; int encontrarNumMenor (int* arr, int count) FindSmallest proc ; mov eax, 7fffffffh ; cmp edx, 0 ;jle Finished ; MainLoop: cmp dword ptr [rcx], eax ; cmovl eax, dword ptr [rcx] ; add rcx, 4 ; dec edx ; jnz MainLoop ; Finished: ret ; FindSmallest endp ; end ;
Con esto finalizamos este tutorial, ya hemos dado un primer vistazo a la programación con Assembly, puede parecer algo complejo al principio pero con un dominio adecuado de C++ y nociones básicas del lenguaje de máquina podemos lograr cosas interesantes y útiles en nuestros desarrollos.

¿Te ayudó este Tutorial?


Sin comentarios, sé el primero!

No esperes más y entra en Solvetic
Deja tus comentarios y aprovecha las ventajas de la cuenta de usuario ¡Únete!

X