En este capítulo se describirá el acceso a las variables desde lenguaje ensamblador y sus propiedades internas.
Las modalidades.La modalidad, es una propiedad que determina como serán tratados las campos de datos en una estructura "regvar" que es la utilizada para guardar variables de TEIMSI. Por ejemplo, sea la instrucción:
var mensaje1="Hola mundo! número77=";
Esta instrucción declara en el módulo raíz la variable "mensaje1", que contiene un texto estático (de longitud 21 bytes). El modo estático es uno de tres tipos de modalidades para variables: modalidad estática (que tiene un contenido fijo dispuesto en la sección de datos), modalidad dinámica, por ejemplo cuando se creó la variable "mensaje1".
La variable "mensaje1" tendrá ahora modalidad dinámica, porque se ha creado una copia asignando memoria por lo cual deja de tener un valor estático de datos constantes.
Y por último está la modalidad temporal, la cual es interna al compilador y no nos llega directamente variable alguna con está modalidad, como ejemplo al analizar:
var mensaje1=trim(ucase("Hola mundo! número77="));
En algún momento el compilador obtuvo la variable ucase("Hola mundo! número77=") ésta variable es temporal e interna, pero en cambio si nos llega el resultado de "trim", función que procesa a tal variable temporal. Es temporal porque surge de la salida de una cadena (en este caso constante) y es usada para crear la variable de salida que interesa (de modalidad dinámica), en efecto la función imode() nos dice con que modalidad de variable se trabaja, ver el siguiente ejemplo:
alert("Modalidad constante ? = " + (imode("Hola mundo! número77=")==_mod_stat) ) // true (verdadero) var lavariable="Hola mundo! número77=" alert("Modalidad dinámica ? = " + (imode(lavariable)==_mod_dina) ) // true (verdadero) alert("Modalidad temporal ? = " + (imode(trim("Hola mundo! número77="))==_mod_engi) ) // true (verdadero)
La importancia de "qué modalidad tiene una variable" reside mayormente para variables tipo de cadena y de tipo matriz, en las cuales se ha asignado un espacio en memoria, porque cada espacio de memoria en esos tipos de datos se ha asignado con una función en ensamblador (llamada NwMemory) la cual nos da un manejador que es número entero largo sin signo utilizado para determinar en tiempo de ejecución de la instrucción; la posición de la cadena o matriz.
En el siguiente ejemplo se observa su uso:
var str1="hola usuario"+_c0 _direct{ mov eax, [str1+reg.vo] NWPOS_eax invoke MessageBox,0, esi, esi, 0 }
La macro "NWPOS_eax" carga el puntero de la cadena en el registro "esi" suponiendo que "eax" contiene el manejador a la cadena en memora asignada con NwMemory, ningún otro registro es modificado por la macro. Por más información ver Introducción al uso de funciones para el manejo de memoria
Un error común es pensar que el puntero a una cadena es siempre igual, pero está sujeto a la posibilidad de cambiar por hacer uso de una función de TEIMSI en una instrucción subsiguiente, como se muestra a continuación:
var str1="hola usuario"+_c0 _direct{ mov eax, [str1+reg.vo] NWPOS_eax push esi } var str2="el cielo es azul"+_c0; _direct{ pop esi invoke MessageBox,0, esi, esi, 0 }
Ese anterior ejemplo muestra código mal hecho, porque el puntero a la cadena str1 pudo haber cambiado. Por ello debe confiarse solamente en el manejador de la cadena en lugar del puntero el cual puede variar en tiempo de ejecución. El siguiente ejemplo es correcto:
var str1="hola usuario"+_c0 _direct{ mov eax, [str1+reg.vo] push eax } var str2="el cielo es azul"+_c0; _direct{ pop eax NWPOS_eax invoke MessageBox,0, esi, esi, 0 }
Existen tres tipos de variables:
1)- Variables públicas
2)- Variables locales
3)- Variables de parámetros pasados a la función en TEIMSI.
Nota: no es lo mismo tipo de variable que tipo de datos en una variable.
La principal distinción entre ellas surge al tratar los datos en ellas desde lenguaje ensamblador.
Las variables públicas pueden accederse desde cualquier función.
El siguiente ejemplo manipula el valor de variables públicas desde ensamblador, no importa si del código el bloque "direct" está en un procedimiento o no:
; //######################################################################################################## var str1="hola usuario", doble1=2.3, entero1=2381, matriz1=array(43,21,11), booleano1=true _direct{ mov eax, [str1+reg.vo] NWPOS_eax mov dword [esi], 'HOLA' ; modifica la cadena ; //################## mov ecx, [str1+reg.nu] mov [entero1+reg.vo], ecx ; modifica el valor de la variable "entero1" ; //################## fld1 fld1 faddp st1, st fsqrt fstp qword [doble1+reg.vo] ; modifica el valor de la variable "doble1" ; //################## ; Una matriz consiste en una cadena con una lista de variables en ella, al principio está el entero largo (dword) que dice cuantos ítems tiene, luego ; está el entero que indica el tamaño total de la cadena actual de la matriz contando los 8 bytes iniciales, y luego viene una secuencia de estructuras ; "regvar" (de tamaño de 16 bytes o 4 dwords) con los ítems que son variables TEIMSI. ; ; A continuación se sumará a cada ítem de la matriz "matriz1" el número 3: mov eax, [matriz1+reg.vo] ; Primero poner en "esi" el puntero a la cadena con la tabla de estructuras "regvar". NWPOS_eax mov ecx, [esi] ; Verifica que la matriz tenga algún ítem. cmp ecx, 0 jz ejemplo_j1 dec ecx ; Se recorrerán los ítems de la matriz desde el último al primero. ejemplo_c1: mov edi, ecx shl edi, 4 ; efectúa edi = ecx * 16 lea edi, [esi+edi+8] ; "edi" ahora apunta a una estructura regvar. cmp dword [edi+reg.ty], syslong ; Asegurarse de que el ítem de la matriz es un entero largo. ("reg.ty" equivale a "regvar.vtype") jnz ejemplo_n1 add dword [edi+reg.vo], 3 ; Suma 3 al ítem de la matriz. ejemplo_n1: dec ecx jns ejemplo_c1 ejemplo_j1: ; //################## xor [booleano1+reg.vo], 1 ; modifica el valor de la variable "booleano1" } alert("Cadena str1 = " + str1 + _nl + "Longitud de la cadena str1 = " + entero1) alert("Raíz cuadrada de 2 = " + doble1) alert("Items de la matriz \"matriz1\" luego de sumar 3 a sus ítems="+_nl+ implode(_nl, matriz1)) alert("La variable \"booleano1\" vale ahora: " + booleano1) ; //########################################################################################################
Las variables de TEIMSI locales una función pueden tratarse como las públicas desde ensamblador, la distinción es que la estructura "regvar" no se halla en la sección de datos sino en la pila local (accedida mediante el registro "ebp").
Las variables en los parámetros de la función deben accederse (desde dentro del procedimiento) primero cargando el puntero hacia la estructura "regvar" de la variable, es decir que el nombre de la variable no es el puntero a una estructura "regvar" sino un lugar en la pila local que aloja el puntero a dicha estructura "regvar". El siguiente ejemplo muestra como leer el valor de una variable pasada como parámetro:
; //################## main(35.4332) function main(lavariable){ var resultado=0.0 _direct{ mov ebx, [lavariable] ; Este paso debe hacerse con cualquier tipo de datos que tenga una variable TEIMSI en el parámetros local. fld qword [ebx+reg.vo] fsqrt fstp qword [resultado+reg.vo] } alert(resultado); } ; //##################