Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

CALL. Una Llamada Perdida (Parte 2)

–Llamada a Funciones CON Argumentos–

De acuerdo, ya aprendimos el sistema básico de la llamada. El único detalle es que no les había dicho que la instrucción RET tiene mas de una forma en código máquina. El OpCode de un RET sin argumentos es C3 hexadecimal y ocupa un solo byte. Existe otro RET que incluye un operando, la función de este operando es equilibrar el Stack Frame para poder introducir argumentos con PUSH. Veamos el mismo ejemplo de la suma de los 2 números que vimos en la nota anterior:

-sección de datos:

A dd 2

B dd 3

C dd ?

-sección de código donde se llama la función:

push [B]

push [A]

call sumar

mov [C], eax

-sección de código donde se ejecuta la función

sumar:

push ebp

mov ebp,esp

virtual at ebp

.ebp_anterior dd ?

.Retorno dd ?

.local_A dd ?

.local_B dd ?

end virtual

mov eax, [local_A]

add eax, [local_B]

leave

ret 8

Revisemos este código paso a paso, pues ahora tenemos un mini stack Frame, o mas bien un Stack Frame sin variables locales. Lo primero que hacemos al entrar al código es empujar a la pila el contenido de EBP, que contiene la base del stack frame anterior. Luego se mueve el contenido del apuntador de Stack ESP a EBP con MOV EBP, ESP.

Directiva Virtual.- Esta es una de las directivas mas importantes del Ensamblador, en este caso del FASM. Si leyeron la nota llamada ‘Signos y Símbolos’, recordarán que lo que le da valor numérico a las etiquetas con la que designamos variables y funciones es algo llamado Location Counter. Como es sabido, el Location Counter comienza a contar desde el inicio del programa. La directiva Virtual de FASM le da su propio Location counter a las variables locales. En este caso se le dice al programa que las variables locales son relativas a EBP.

Etiquetas Relativas.- Poner un punto antes de una etiqueta permite usar etiquetas locales. Esas son relativas a las etiquetas globales. Es decir que podemos usar una y otra vez una etiqueta como ‘.resultado’ si antes de cada copia ponemos una etiqueta global. Las etiquetas globales no tienen punto.

Etiquetas no inicializadas.- Cuando uno escribe = etiqueta dd ? Lo que decimos es que la etiqueta llamada ‘etiqueta’ hace referencia a una palabra de 32bits (DWORD) que NO está inicializada. Aparte de que el Stack Frame es una estructura de datos dinámica. (Esto es decir que no se queda quieta y que se crea y destruye en diferentes sitios conforme se ejecuta el código) Si inicializáramos los datos de entrada dentro de la función destruiríamos los datos de entrada de la función. El signo de interrogación indica que una variable no está inicializada.

Retorno y ebp anteriores.- Como la directiva Virtual apunta directamente a EBP y este tiene el esp antiguo, lo que hay en el stack son el EBP anterior y la posición de retorno en ese orden. Para cada uno de estos datos se usa un DWORD de 32 bits o 4 celdas de memoria.

.local_A y .local_B.- Estos son los argumentos de entrada. Son dos dwords en la memoria desde donde se pueden leer los argumentos de entrada. Aquí es donde se explica porque los argumentos de una función se introducen a la pila desde el último hasta el primero.

End virtual.- Esto indica el fin de las direcciones dadas por la directiva Virtual. Fuera de aquí, sigue siendo el location counter el que dicta los valores de las etiquetas.

Leave.- Existe otra pareja de instrucciones de Intel dedicadas a manejar el Stack Frame: Enter y Leave. El problema es que al parecer Windows no usa Enter porque tiene limitaciones en cuanto al nivel de anidamiento de los procesos. Leave lo que hace es reiniciar el stack frame y equilibrar la parte negativa de la pila. Mas información en los manuales de Intel.

RET 8.- Este ret tiene una pequeña diferencia. Ese 8 significa que luego de obtener la dirección de retorno, es necesario desaparecer 8 bytes del stack para mantenerla equilibrada. Este parámetro es igual a la cantidad de celdas de byte que se usan para el paso de argumentos. Como en este caso tenemos 2 Dwords de 4 bytes cada uno, el total es de 8 bytes.

Hay otro detalle, el código también podría ser el siguiente:

mov eax, [ebp + 8]

add eax, [ebp + 0ch]

y no habría necesidad de usar la directiva virtual. De hecho, esto es lo que nos mostraría un desensamblador si introdujéramos el código de arriba.

De acuerdo, ahora tan solo nos hace falta una tercera y última parte de esta serie sobre CALL para poder seguir analizando el código de la ventana. Por ahora mejor prepárense porque pronto ya no vamos a saber donde termina el Ensamblador y comienza la programación en Windows.

Anuncios

enero 19, 2009 - Posted by | Uncategorized

Aún no hay comentarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: