5.14 Uniones
Mientras que cada campo en una estructura tiene un desplazamiento relativo al primer byte de la estructura, todos los campos en una unión empiezan en el mismo desplazamiento. El tamaño de almacenamiento de una unión es igual a la longitud de su campo más grande. Cuando no forma parte de una estructura, una unión se declara mediante las directivas UNION y ENDS:
nombreunión UNION campos-de-la-unión nombreunión ENDS
Si la unión se anida dentro de una estructura, la sintaxis es un poco distinta:
nombreestruc STRUCT campos-de-la-estructura UNION nombreunión campos-de-la-unión ENDS nombreestruc ENDS
Las declaraciones de los campos en una unión siguen las mismas reglas que para las estructuras, con la excepción de que cada campo sólo puede tener un inicializador. Por ejemplo, la unión Entero tiene tres atributos de tamaño distintos para los mismos datos, e inicializa todos los campos con cero:
Entero UNION D DWORD 0 W WORD 0 B BYTE 0 Entero ENDS
Sea consistente Si se utilizan los inicializadores, deben tener valores consistentes. Suponga que Entero se declara con distintos inicializadores:
Entero UNION D WORD 1 W WORD 5 B BYTE 8 Entero ENDS Entonces, declararíamos una variable Entero llamada miEnt, usando los inicializadores predeterminados:
.data miEnt Entero <>
Los valores de miEnt.D, miEnt.W y miEnt.B serían todos iguales a 1. El ensamblador ignoraría los inicializadores declarados para los campos W y B.
Estructura que contiene una uniónpodemos probar una unión dentro de una estructura, usando el nombre de la unión en una declaración, como hemos hecho a continuación para el campo IDArchivo dentro de la estructura
InfoArchivo, InfoArchivo STRUCT IDArchivo Entero <> NombreArchivo BYTE 64 DUP(?) InfoArchivo ENDS
O puede declarar una unión directamente dentro de una estructura, como hemos hecho a continuación para el campo IDArchivo:
InfoArchivo STRUCT UNION IDArchivo D DWORD ? W WORD ? B BYTE ? ENDS NombreArchivo BYTE 64 DUP(?) InfoArchivo ENDS
Declaración y uso de variables de unión:Una variable de unión se declara y se inicializa en forma muy parecida a una variable de estructura, con una importante diferencia: no se permite más de un inicializador. A continuación se muestran ejemplos de variables tipo Entero:
val1 Entero <12345678h> val2 Entero <100h> val3 Entero <>
Para utilizar una variable de unión en una instrucción ejecutable, debemos suministrar el nombre de uno de los campos variantes. En el siguiente ejemplo, asignamos valores de los registros a los campos de la unión Entero. Observe la flexibilidad que tenemos al poder usar distintos tamaños de operandos:
mov val3.B, al mov val3.W, ax mov val3.D, eax
Las uniones también pueden contener estructuras. La siguiente estructura llamada INPUT_RECORD la utilizan algunas funciones de entrada de consola de MS Windows. Contiene una unión llamada Event, la cual selecciona uno de varios tipos de estructuras predefinidas. El campo EventType indica el tipo de registro que aparece en la unión. Cada estructura tiene una distribución y tamaño distintos, pero sólo se utiliza una a la vez:
INPUT_RECORD STRUCT EventType WORD ? ALIGN DWORD UNION Event KEY_EVENT_RECORD <> MOUSE_EVENT_RECORD <> WINDOW_BUFFER_SIZE_RECORD <> MENU_EVENT_RECORD <> FOCUS_EVENT_RECORD <> ENDS INPUT_RECORD ENDS A menudo, la API Win32 incluye la palabra RECORD al nombrar las estructuras.1 Ésta es la definición de una estructura KEY_EVENT_RECORD:
KEY_EVENT_RECORD STRUCT bKeyDown DWORD ? wRepeatCount WORD ? wVirtualKeyCode WORD ? wVirtualScanCode WORD ? UNION uChar UnicodeChar WORD ? AsciiChar BYTE ? ENDS dwControlKeyState DWORD ? KEY_EVENT_RECORD ENDS
|