2011-10-06 4 views
3

Considérons le programme C:confusion sur l'alignement des données ARM9

int main(void) 
{ 
    char string[10] __attribute__ ((aligned(32))); 
    int i; 
    int *intp = (int*)(string + 1); 

    printf("string: 0x%x, intp: 0x%x\n", string, intp); 

    for (i=0; i<10; i++) 
    { 
     string[i] = 10; 
    } 
    dump(string); 

    printf("*intp: 0x%x\n", *intp); 

    *intp = 0xEEEEEEEE; 
    dump(string); 

    return 0; 
} 

Je forçaient essentiellement CPU est d'accéder à un 32 bits de données (int) à une adresse désaligné. TBH J'espérais une erreur de disque sur ma carte ARM9. Mais au lieu que je suis un résultat intéressant/confusion:

Après avoir réglé intp à 0xEEEEEEEE, le dumping de la chaîne montre:

0xee, 0xee, 0xee, 0xee, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa  

Ainsi, le code a changé en fait le premier élément dans la chaîne! Pourquoi?

Merci,

+0

curiosité: Qu'advient-il si vous essayez 'int * intp = (int *) (string + 2);'? Que diriez-vous de +3? – cnicutar

+0

@cnicutar: en fait +2 ou +3 ne ferait pas de différence! – lang2

Répondre

5

Très probablement la CPU « tours » adresses mal alignées, de sorte que lorsque vous passez une adresse désaligné à une certaine instruction, le matériel trouve le plus proche frontière et effectue une opération sur cette adresse.

This pourrait vraiment répondre à votre question:

sur le bras et StrongArm, si vous demandez un mot non-alignés et vous ne prenez pas le piège d'alignement, alors vous obtenez le mot aligné mis en rotation de telle sorte que l'octet que vous avez demandé soit dans le LSB. Par exemple,

Consider: 
     Address: 0 1 2 3 4 5 6 7 
     Value : 10 21 66 23 ab 5e 9c 1d 

Using *(unsigned long*)2 would give: 
     on x86: 0x5eab2366 
     on ARM: 0x21102366