O único sistema que é construído sob este modelo de dados é o Windows, da Microsoft, bem como aplicações para ele desenvolvidas pela Microsoft. No sistema operativo
Windows de 64 bits somente o tipo de dados pointer é expandido para 64 bits, enquanto
que os tipos de dados int e long mantêm o tamanho de 32 bits, como no modelo ILP32 [15][29][30][31][32].
Inicialmente, a maioria das aplicações de 64 bits da Microsoft provinham das de 32 bits, as quais eram reescritas e recompiladas por forma a poderem ser executadas em ambos os sistemas operativos, Windows de 32 e de 64 bits. Para tal, foi necessário assegurar que o modelo de dados somente afectava o tipo de dados pointer, uma vez que este passou a um comprimento de 64 bits, e definir novos tipos de dados que permitissem relacionar os tamanhos dos ponteiros. Isto veio permitir que, ao alterar o tamanho do tipo de dados ponteiro de 32 para 64 bits, o tamanho dos dados associados ao ponteiro também se alterasse. No entanto, os tipos de dados primitivos mantêm o seu tamanho em 32 bits, facilitando a recompilação das aplicações de 32 bits, por não haver, por exemplo, quaisquer alterações do tamanho dos dados em suportes de memória secundária (disco rígido), partilha de dados em rede de computadores, ou partilha de dados através de mapeamento de memória de ficheiros [29][30][31].
Se tivermos em conta a relação entre os tipos de dados da linguagem de programação C++ (linguagem de programação proveniente da linguagem C e utilizada pela Microsoft) com o tipo de dados ponteiro, a mesma em C++ não é garantida, uma vez que se assume que o tamanho de um ponteiro é igual ao do tipo de dados inteiro de maior largura. Onde este está associado à largura do barramento de endereços do processador (tipo de dados ponteiro) com o tamanho da palavra do processador (tipo de dados inteiro de maior largura). Contudo, tal suposição não é correcta, fazendo com que em
programação tenhamos de forçar uma dada variável a um tipo de dados (cast), originando perda de dados. Por exemplo, se considerarmos um processador de espaço de endereçamento de 48 bits e comprimento de palavra de 16 bits, iremos perder informação quando atribuirmos aos 16 bits os 48 bits [29][30][31].
Tipo de Dado C++ [windows] win16 (bits) win32 (bits)
(unsigned) short [WORD] 16 16
(unsigned) int [UINT] 16 32
(unsigned) long [DWORD] 32 32
void * ??? 32
void near * 16 N/A
void far * 32 N/A
??? – desconhecido N/A – Não Aplicável
Tabela 2.9: Tipos dados e tamanhos em Windows
Definição do Tipo de Dado Tipo de Dado Windows
typedef unsigned long DWORD
typedef long LONG
typedef int BOOL
typedef unsigned char BYTE typedef unsigned short WORD
typedef short SHORT
typedef float FLOAT typedef FLOAT *PFLOAT typedef BOOL near *PBOOL typedef BOOL far *LPBOOL typedef BYTE near *PBYTE typedef BYTE far *LPBYTE typedef int near *PINT typedef int far *LPINT typedef WORD near *PWORD typedef WORD far *LPWORD typedef long far *LPLONG typedef DWORD near *PDWORD typedef DWORD far *LPDWORD typedef void far *LPVOID
typedef int INT
typedef unsigned int UINT typedef unsigned int *PUINT
Tabela 2.10: Extracto da biblioteca windef.h, da Microsoft
Em Windows existem diversos tipos de tamanhos de ponteiros, representados por 16 bits (near pointer) e por 32 bits (far pointer), os quais são visíveis já nas aplicações de 16 bits (Tabela 2.9). Comparando os modelos aplicacionais de 16 e 32 bits em Windows, verifica-se que somente houve alteração no tamanho do tipo de dados inteiro (int).
A Microsoft não utiliza directamente os tipos de dados primitivos da linguagem. Define tipos de dados (typedefs) para representar os mesmos, como se pode observar na Tabela 2.10, e outros para representar tipos de dados não existentes na linguagem.
Na biblioteca windef.h, representada pela Tabela 2.10, estão definidas as equivalências de tipos de dados, bem como a definição de novos tipos de dados.
Os tipos de dados DWORD e LONG são os mais utilizados no Windows, que comparativamente com a linguagem C++ seriam, respectivamente, os tipos de dados int e
long. No entanto, o tipo de dado DWORD é utilizado quando se pretende representar um
número inteiro positivo demasiado grande, uma vez que ele é equivalente ao unsigned
long. Os tipos de dados BYTE e SHORT são utilizados para representar o tipo de dados
inteiro de 1 byte (8 bits = char) e o inteiro de 2 bytes (16 bits = short), respectivamente. Por seu turno, os tipos de dados ponteiro, de prefixo P ou LP, referenciam ponteiros dos tipos de dados inteiros de 16 bits (P = near pointer) e de 32 bits (LP = far pointer = long
pointer), respectivamente.
Os tipos de dados das aplicações win32 (Tabela 2.10) são utilizados na sua íntegra no modelo de dados LLP64. O problema coloca-se, na recompilação de uma aplicação
win32 para win64, quando um ponteiro de 32 bits é atribuído a um tipo de dados inteiro
ou longo inteiro, ou quando, no desenvolvimento de aplicações win64, é necessário utilizar inteiros de 64 bits, em vez de utilizar DWORD ou LONG (ambos de 32 bits). Para ambas as situações, a Microsoft definiu novos tipos de dados para manipulação de inteiros, como o int64 (long long), e ponteiros de 64 bits.
Em suma, podemos dizer que o modelo de dados utilizado pela Microsoft é único e feito à medida, porque se todas as aplicações desenvolvidas até então, independentemente da plataforma aplicacional (win16 ou win32), assentavam em tipos de dados definidos pela própria Microsoft, ignorando os oferecidos pela linguagem de programação, e se as aplicações win64 são oriundas das win32, então é mais fácil construir um modelo de dados de 64 bits que aproveite os tipos de dados existentes em
win32 do que reescrever por completo as aplicações de win32 e/ou construir as aplicações win64, tendo por base um dos outros modelos de dados de 64 bits, os quais assentam nos
tipos de dados inteiros primitivos da linguagem de programação que se expandem de 32 para 64 bits.
Para um melhor entendimento da não adopção dos outros modelos de dados (ILP64 e LP64), se recompilarmos, de win32 para win64, a estrutura de dados do
cabeçalho de um ficheiro bitmap (de extensão bmp) (Figura 2.2) [31] para um desses modelos, o tipo de dado LONG expande-se de 32 para 64 bits, levando a que o programa de 64 bits não consiga identificar os diversos componentes que compõem o cabeçalho do ficheiro, e consequentemente não poderá utilizar a estrutura de dados, pelo facto de alguns dos tipos de dados terem aumentado de tamanho.
typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
Figura 2.2: Estrutura de dados do cabeçalho de um ficheiro de bitmap, em Windows