Si vous parlez de convertir un exécutable binaire, c'est faisable, mais ce n'est pas facile.
C'est plus facile sur les architectures à instructions de longueur fixe - ce qui signifie : pas Intel. En effet, il est très facile de parcourir le code et de trouver quelles parties sont des instructions, et quelles parties sont des données.
Il est en fait plus facile de fournir une couche de compatibilité, si, lorsqu'il est en mode 64 bits, le processeur est capable d'exécuter des processus individuels en mode 32 bits.
Vous pouvez également faire ce qu'on appelle une "recompilation dynamique" du code binaire. C'est ainsi que Rosetta a pu permettre aux binaires de PowerPC Mac OS X de fonctionner sur Intel Mac OS X jusqu'à Mac OS X avant Leopard (en fait, je les ai fait fonctionner sur Leopard, dans mon bureau, mais B&I ne voulait pas maintenir des archives binaires séparées).
Alternativement, vous pouvez émuler l'environnement d'exécution 32 bits en utilisant un programme émulateur ; pour Intel, ce serait probablement QEMU ou quelque chose de similaire.
Si vous parlez du code source, c'est à la fois plus facile, et plus difficile.
Vous pouvez recompiler le code source avec un compilateur qui cible l'environnement d'exécution 64, au lieu de l'environnement d'exécution 32 bits.
Cela vous permettra de faire une partie du chemin ; malheureusement, cela ne vous permettra pas de faire tout le chemin, car beaucoup de code fait des hypothèses sur les tailles des types de données. Joli commun est la conversion entre pointeur et int, int et long, et les promotions et rétrogradations de types similaires.
Ceux-ci peuvent entraîner une perte de données, une perte de précisions, ou des erreurs pures et simples dans le code - par exemple, le code étant utilisé pour représenter les champs de bits et autres données, qui sont maintenant de la mauvaise taille.
Il y a aussi le problème des données externes.
This is most obvious in networking, since the structures passed back and forth as packets tend to have very strict field size requirements.
You can also have a problem with external data prepresentation; if you saved something out as a:
- struct foo {
- long i;
- char str[20];
- ...
- };
This will not have the same on disk representation in ILP32 (Integer, Long, and Pointer are 32 bits) and LP64 (Integer is 32 bits; Long and Pointer are 64 bits).
ILP32 and LP64 are the most common ways of implementing 32 vs. 64 bit data types in most computer language implementation; there are actually other possibilities, which are less commonly used.
En outre, il y a des problèmes entre les compilations 32 et 64 bits entourent le packing des structures (combien d'espace est alloué pour atteindre une limite d'alignement interne à la structure) et le padding des structures (combien d'espace est alloué à la fin de la structure, de sorte que, dans un tableau de structures, le 0e et le 1er élément ont les mêmes limites d'alignement), et ainsi de suite.
Il existe des outils pour automatiser une grande partie de ce travail ; le plus important est d'activer tous les avertissements de conversion de type et de conversion de taille dans votre compilateur, et d'en faire des erreurs. Mais il y a aussi des outils d'analyse statique, et il y a des outils d'analyse de code objet (binaires avec des symboles, pas nécessairement des exécutables, mais au minimum : des unités de compilation).
En bref, l'un ou l'autre type de conversion peut demander beaucoup d'efforts à réaliser*.
(*) Oui, j'ai fait cela de multiples fois, et sur de multiples architectures, tout au long de ma carrière.