Vous êtes sur la page 1sur 4

LENGUAJE EMSNAMBLADR

Introduccin al lenguaje ensamblador IL de .NET [Parte 3]


Publicado por JuDelCo el 17 diciembre 2011 Posted in: Programacin. 2 comentarios [ <-- Introduccin al lenguaje ensamblador IL de .NET [Parte 2] ]

Declaracin de Variables
Las variables es uno de los pilares de cualquier lenguaje de programacin y por tanto, ILAsm nos permite declararlas y usarlas. Aunque no es una tarea tan sencilla como en los lenguajes de alto nivel, usando la directiva .locals podremos definir variables. Esta directiva debera normalmente usarse al principio de cualquier mtodo, aunque puedes poner la declaracin en cualquier sitio, obviamente, antes de usarlas. Aqu tenemos un ejemplo en el que declaramos una variable, guardamos un valor en ella y luego la usamos para imprimir su valor.
.locals init (int32, string) ldc.i4 34 stloc.0 ldstr "Texto de ejemplo para probar la variable local" stloc.1 ldloc.0 call void [mscorlib]System.Console::WriteLine(int32) ldloc.1 call void [mscorlib]System.Console::WriteLine(string)
Figura 1.5 Variables Locales

Hemos declarado dos variables usando la directiva .locals, una del tipo int32 y la otra del tipo string. Luego hemos cargado el nmero 34 del tipo int32 en memoria y se la hemos asignado a la variable local 0, la cual es nuestra primera variable local. Toma nota que en ILAsm los ndices empiezan por cero. Luego hemos cargado en memoria una segunda variable y se la hemos asignado a esa segunda variable local. Finalmente hemos mostrado por pantalla ambas variables. Os preguntareis para qu sirve la instruccin ldloc, pues bien, puede ser usada para cargar cualquier tipo de dato en memoria (enteros, coma flotante, objetos, etc). En este caso no hemos usado nombres para nuestras variables. Ya que son locales y no tenemos intencin de utilizarlas fuera de nuestro mtodo. Eso no significa que no se puedan declarar variables por su nombre. Para declarar esas variables, simplemente hazlo al igual que en otro lenguaje de alto nivel como por ejemplo .locals init (int32 x, int32 y). Despus podrs leer o guardar valores en esas variables usando las mismas instrucciones, pero usando sus nombres como stloc x y ldloc y. Aun as, aunque tengan sus propios nombres, podrs seguir accediendo a ellas mediante su ndice. Nota: A lo largo de todos los tutoriales usar variables sin nombre, para que te acostumbres a pensar en qu indice estn guardadas tus variables.

Bien, ahora tienes una idea de cmo manipular variables y stacks. Por favor revisa los cdigos si an no tienes muy claro algn concepto y que, a partir de ahora, estaremos manipulando ambos con bastante frecuencia. Por ello es necesario que te familiarices con este procedimiento (definir/inicializar, guardar y leer sus valores).

Condiciones en ILAsm
Las condiciones son otros de los pilares de cualquier lenguaje de programacin. En los lenguajes de bajo nivel, como cualquier otro lenguaje ensamblador, las condiciones estn hechas usando saltos (o ramificaciones). Tomemos un ejemplo de esto:
br SaltarAqui //Tambin puedes usar br.s si lo deseas //El cdigo que haya aqu ser saltado despus de la instruccin anterior SaltarAqui: //En cambio, estas instrucciones sern ejecutadas

Compara esa instruccin con la instruccin goto de un lenguaje de alto nivel. Funciona igual verdad ? La instruccin saltar el punto de ejecucin a la etiqueta indicada. Aqu, en ILAsm, en vez de usar goto usaremos br. Es instruccin tambin puede ser usada utilizando br.s si ests seguro de que el destino est entre los -128 y +127 bytes anteriores-posteriores a este, ya que usar un int8 en vez de un int32 para el offset. El ejemplo de arriba ha sido una ramificacin (salto) incondicional ya que no hubo ninguna condicin anterior de la instruccin que indicase lo contrario. Tomemos pues un ejemplo en el que s contemplaremos un ejemplo con un salto condicional:
//Saltando.il .method static void main() cil managed { .maxstack 2 .entrypoint //Cogemos el primer valor del usuario ldstr "Introduce el Primer nmero: " call void [mscorlib]System.Console::WriteLine (string) call string [mscorlib]System.Console::ReadLine () call int32 [mscorlib]System.Int32::Parse(string) //Cogemos el segundo valor del usuario ldstr "Introduce el Segundo nmero: " call void [mscorlib]System.Console::WriteLine (string) call string [mscorlib]System.Console::ReadLine () call int32 [mscorlib]System.Int32::Parse(string) ble Menor ldstr "El segundo nmero es menor que el primero." call void [mscorlib]System.Console::WriteLine (string) br Salida Menor:

ldstr "El primer nmero es menor que el segundo." call void [mscorlib]System.Console::WriteLine (string) Salida: ret }
Figura 1.6 Saltando.il (solamente el mtodo main)

El cdigo de arriba toma dos valores del usuario y entonces consulta cual de ellos es el ms pequeo. La instruccin la cual requiere nuestra atencin es ble Menor, la cual indica al JIT a mirar si el primer valor en el stack es menor o igual que el segundo, si as es el caso, entonces saltar a la etiqueta Menor. En el caso contrario la ejecucin del programa continuar por la siguiente instruccin, sin realizar el salto, sin embargo luego se encontrar con un salto incondicional, ya que si no estuviera ah, el programa continuara y ejecutara las instrucciones contenidas en la etiqueta Menor. Por ello hemos creado una nueva etiqueta llamada Salida y hemos llamado a la instruccin br Salida la cual obligar al programa a saltar a la etiqueta Salida y ejecutar la instruccin ret, para finalizar el mtodo. Las otras instrucciones condicionales que podemos encontrar son beq (==), bne (!= ), bge (>= ), bgt (>), ble (<= ), blt (<), adems de brfalse y brtrue (para comprobar si el primer elemento del stack es cero o no respectivamente). Puedes usar cualquiera de ellas para ejecutar alguna parte de tu cdigo y evitar (saltar) otro. Como dije antes, no tenemos la facilidad que tenemos en los lenguajes de alto nivel, por ello todo debe de ser realizado por ti mismo si tienes pensado escribir o modificar cdigo en ILAsm.

Bucles en ILAsm
Los bucles son otra parte fundamental de un lenguaje de programacin. Un bucle no es otra cosa que la repeticin del mismo bloque de cdigo una vez y otra vez. Para ello la repeticin del bloque depender de una variable a la que llamaremos ndice del bucle. En el siguiente fragmento de cdigo mostrar un ejemplo de cmo funciona un bucle bsico, as que dedicale un poco de tiempo a entender cmo funcionan los bucles:
.method static void main() cil managed { //Definimos dos variables locales variables .locals init (int32, int32) .maxstack 2 .entrypoint ldc.i4 4 stloc.0 ldc.i4 0 stloc.1 //Tope, el lmite del bucle. Haremos 5 repeticiones //Inicializamos el ndice a cero

Comienzo: //Comprobamos si el contador del ndice ha superado el lmite ldloc.1 ldloc.0 bgt Salida //Si la segunda variable supera a la primera, entonces saltamos

ldloc.1 call void [mscorlib]System.Console::WriteLine(int32) //Incrementamos el contador ldc.i4 1 ldloc.1 add stloc.1 br Comienzo Salida: ret }
Figura 1.7 Bucles.il (solamente el mtodo main)

En C#, este cdigo se vera de esta manera:


for (temp = 0; temp < 5; temp++) System.Console.WriteLine (temp);

Bien, examinemos el cdigo. Primero, hemos declarado dos variables locales e inicializado la primera con un valor de 4 y la segunda con valor 0. El bucle real empieza con la etiqueta Comienzo, desde donde primero comprobaremos si el contador del indice del bucle (la variable n2, ldloc 1) sobrepasa el lmite impuesto por nuestra primera variable (ldloc 0), si ese fuera el caso, el programa saltara a la etiqueta Salida con lo cual nuestro programa terminara. Si no es el caso, entonces el valor ser escrito por pantalla e incrementaremos ese valor para luego saltar de nuevo a la etiqueta Comienzo para comprobar de nuevo si el contador ha excedido o no el lmite impuesto. As funcionan los bucles en ILAsm (y en la mayora de los otros lenguajes ensamblador)

http://judelco.wordpress.com/2011/12/17/introduccion-al-lenguaje-ensamblador-il-de-netparte-3/

Vous aimerez peut-être aussi