AMD64

De ClissXXI.

  • Détecter un processeur 64bit: cherche le flag lm:
cat /proc/cpuinfo  | grep --color -w lm
  • Compiler en 32bit sous AMD64:
aptitude install lib32gcc1 libc6-dev-i386
cat <<EOF | gcc -xc -o test32 - -m32
#include <stdio.h>
int main() { printf("sizeof(int) = %d, sizeof(void*) = %d\n", sizeof(int), sizeof(void*)); }
EOF
  • Détecter un exécutable 32 ou 64:
$ file test32
test32:  ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.0, dynamically linked (uses shared libs), for GNU/Linux 2.6.0, not stripped
$ file test64
test64:  ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.0, dynamically linked (uses shared libs), for GNU/Linux 2.6.0, not stripped
  • Exécuter en 32bit sous AMD64: aucune manipulation particulière, mais il faut avoir les dépendances 32bit installées:
$ ./test32
sizeof(int) = 4, sizeof(void*) = 4
$ ./test64
sizeof(int) = 4, sizeof(void*) = 8


  • Détecter un noyau (pas un processeur) 64bit:
$ uname -m
x86_64
  • Simuler un noyau 32bit:
$ aptitude install linux32
$ linux32 uname -m
i686
# mais ça ne fait rien d'autre que ça
  • Lancer un VServer installé en 32bit sous 64bit: aucune manipulation.

Test GCC plus poussé

#include <stdio.h>

struct test_alignment
{
  int a, b, c;
};
struct test_alignment2
{
  int a;
  int *p;
};
struct test_alignment3
{
  int a;
  double d;
};


int main(void)
{
  struct test_alignment s[3];
  struct test_alignment2 s2[3];
  struct test_alignment3 s3[3];
  printf("sizeof(int)       = %d\n", sizeof(int));
  printf("sizeof(void*)     = %d\n", sizeof(void*));
  printf("sizeof(long)      = %d\n", sizeof(long));
  printf("sizeof(long long) = %d\n", sizeof(long long));
  printf("sizeof(double)    = %d\n", sizeof(double));
  printf("sizeof(struct test_alignment[0])  = %d\n", sizeof(s[0]));
  printf("sizeof(struct test_alignment*3)   = %d\n", sizeof(s));
  printf("sizeof(struct test_alignment2[0]) = %d\n", sizeof(s2[0]));
  printf("sizeof(struct test_alignment2*3)  = %d\n", sizeof(s2));
  printf("sizeof(struct test_alignment3[0]) = %d\n", sizeof(s3[0]));
  printf("sizeof(struct test_alignment3*3)  = %d\n", sizeof(s3));
  return 0;
}
# ./test32
sizeof(int)       = 4
sizeof(void*)     = 4
sizeof(long)      = 4
sizeof(long long) = 8
sizeof(double)    = 8
sizeof(struct test_alignment[0])  = 12
sizeof(struct test_alignment*3)   = 36
sizeof(struct test_alignment2[0]) = 8
sizeof(struct test_alignment2*3)  = 24
sizeof(struct test_alignment3[0]) = 12
sizeof(struct test_alignment3*3)  = 36

# ./test64
sizeof(int)       = 4
sizeof(void*)     = 8
sizeof(long)      = 8
sizeof(long long) = 8
sizeof(double)    = 8
sizeof(struct test_alignment[0])  = 12
sizeof(struct test_alignment*3)   = 36
sizeof(struct test_alignment2[0]) = 16
sizeof(struct test_alignment2*3)  = 48
sizeof(struct test_alignment3[0]) = 16
sizeof(struct test_alignment3*3)  = 48

On remarque donc que:

  • int garde la même taille
  • void* double naturellement (plus grand adressage mémoire), mais aussi long
  • long long et double ne bougent pas
  • le compilateur continue d'aligner des blocs de 4 octets sur des multiples de 4 octets
  • le compilateur aligne en revanche des blocs de 8 octets sur des multiples de 8 octets en 64bit, et non plus de 4 octets comme en 32bit

Conclusion: sur du code très courant, l'alignement ne changera pas, mais des changements surviennent tout de même facilement.

Outils personnels