2011-12-07 4 views
1

J'ai rencontré un problème lors de la compilation d'un paquet autour, je ne suis pas vraiment un bon codeur, mais j'ai essayé de le réparer pour moi-même, et il ne compilera toujours pas . Ceci est le bit de code d'origine .:erreur: contrainte de registre impossible dans 'asm'

#ifdef __GNUC__ 
asm("and $3, %%ecx;" 
"shl $3 ,%%ecx;" 
"ror %%cl, %0" 
: "=r" (value) 
: "r" (value), "c" (address)); 
#else 

L'erreur est:.

GBAinline.h: 139: Erreur: contrainte de registre impossible dans 'asm' (ligne ifdef est 138)

Et voilà comment j'ai essayé de le faire paraître .:

#ifdef __GNUC__ 
asm ("and $3 %%ecx,shl $3 %%ecx,ror %%cl, %0" : "=r" (value): "r" (value), "c" (address)); 

#else 

Pourtant, cela ne fonctionnerait pas. C'est un émulateur gba avant tout le monde, VBA, et c'est partie de GBAinline.h. Cet assembleur me rend déjà fou.

Edit .: Le problème ci-dessus a été géré très bien, je ne faisais pas attention à quel compilateur j'utilisais. Mais maintenant j'obtiens cette erreur sur ce morceau de code d'un fichier d'en-tête, je l'ai mis sur pastebin, pour garder les choses ici un peu plus ordonnées ... (Désolé si c'est faux, je peux le changer plus tard)

C'est l'en-tête qui a les lignes qui se traduit par des erreurs .: http://pastebin.com/k3D4cg0d

Et ceci est le fichier C .: il se réfère à http://pastebin.com/Ymg1X5dg

cela donne une erreur comme celui-ci .:

/var/tmp/cc3zA0lH.s: Assembler messages: /var/tmp/cc3zA0lH.s:69: Error: bad instruction `sw $3,0(r3)', 

Et ainsi de suite pour le reste de ces lignes.

+0

Le code d'origine semble correct pour moi. Quel copilote et quelle plate-forme êtes-vous, par ex. Que fait la sortie 'gcc -v'? Vous devez gérer l'assemblage x86 et les contraintes [gcc inline assembly] (http://gcc.gnu.org/onlinedocs/gcc/Constraints.html) pour bien comprendre ce code. –

+0

Merci pour la réponse Mackie, mon gcc est arm-linux, c'est peut-être le problème, ce code est conçu pour x86, et je ne l'ai pas remarqué. Aussi, merci pour le lien, je vais le regarder. – Luis

+0

Donc, j'ai utilisé un compilateur x86, et cela a fonctionné comme un charme! Merci Mackie, je n'avais pas fait attention à ça. – Luis

Répondre

1

Cet ensemble en ligne est bogué:

  1. Il utilise des chaînes multi-lignes qui concatènent efficacement. Sans \n tout apparaît sur une ligne. Si votre assembleur accepte instructions séparées par des points-virgules fait toute la différence là-bas ... certains ne peuvent pas.
  2. Il spécifie la même variable que la contrainte d'entrée/sortie au lieu d'utiliser "+r"(value) comme suggéré habituellement pour cette situation.

Sans voir le reste du code, il n'est pas tout à fait clair pourquoi l'instruction assembly en ligne ressemble à ce qu'elle fait; Personnellement, je vous suggère d'écrire comme:

asm("ror %%cl, %0" : "+r"(value) : "c"((((uintptr_t)address) & 3) << 3))); 

parce qu'il ya peu de besoin de faire le calcul lui-même dans l'assemblage. Le casting uintptr_t (à partir de <stdint.h>) rend cet agnostique 32/64bit ainsi.

Edit:

Si vous le voulez pour un autre CPU mais x86/x64, il doit évidemment être différent ...Pour ARM (pas Thumb2), ce serait:

asm("ROR %0, %0, %1" : "+r"(value) : "r"((((uintptr_t)address) & 3) << 3))); 

puisque c'est comment l'instruction se comporte rotate il.

Modifier (ajouter la référence):

En ce qui concerne l'opération effectuée ici en tant que telle, this blog post donne une perspective intéressante - à savoir que le compilateur est tout à fait susceptible de créer la même sortie pour:

(a >> shift | a << (8 * sizeof(a) - shift)) 

que pour la ligne x86

asm("ror %%cl, %0" : "+r"(a) : "c"(shift)) 

Test ceci:

#include <stdint.h> 

int main(int argc, char **argv) 
{ 
    unsigned int shift = (int)((((uintptr_t)argv) & 3) << 3); 
    unsigned int a = argc; 
#ifdef USE_ASM 
    /* 
    * Mark the assembly version with a "nop" instruction in output 
    */ 
    asm("nop\n\t" 
     "ror  %%cl, %0" : "+r"(a) : "c"(shift)); 
    return a; 
#else 
    return (a >> shift | a << (8 * sizeof(a) - shift)); 
#endif 
} 

Compile/désassembler il:

$ gcc -DUSE_ASM -O8 -c tf.c; objdump -d tf.o 

tf.o:  file format elf64-x86-64 

Disassembly of section .text: 

0000000000000000 : 
    0: 83 e6 03    and $0x3,%esi 
    3: 8d 0c f5 00 00 00 00 lea 0x0(,%rsi,8),%ecx 
    a: 90      nop 
    b: d3 cf     ror %cl,%edi 
    d: 89 f8     mov %edi,%eax 
    f: c3      retq 
$ gcc -O8 -c tf.c; objdump -d tf.o 

tf.o:  file format elf64-x86-64 

Disassembly of section .text: 

0000000000000000 : 
    0: 83 e6 03    and $0x3,%esi 
    3: 8d 0c f5 00 00 00 00 lea 0x0(,%rsi,8),%ecx 
    a: d3 cf     ror %cl,%edi 
    c: 89 f8     mov %edi,%eax 
    e: c3      retq

Ergo, cet ensemble en ligne est inutile.

+0

Merci Frank, mais j'ai d'autres fichiers qui étaient censés fonctionner sous le bras. Encore ça me donne des problèmes, avec ces erreurs /var/tmp/cc3zA0lH.s: Messages de l'assembleur: /var/tmp/cc3zA0lH.s:69: Erreur: mauvaise instruction 'sw $ 3,0 (r3) ', ce que j'ai encore Je crois qu'il s'agit d'un problème de gcc, et non pas de celui du fichier, et qu'il s'agit d'environ 25 lignes d'erreurs, je suppose qu'il est inutile de tout publier car elles sont toutes semblables. Désolé pour mon désordre ici, j'essaye toujours de comprendre comment les commentaires d'affichage fonctionnent, mais j'essaye. Encore une fois, merci pour les réponses – Luis

+0

@Luis: 'sw $ 3,0 (r3)' ressemble à une instruction MIPS, pas x86 ou ARM. Vous devez configurer votre environnement correctement ... –

+0

@Mackie: ack, ressemble à un problème de configuration de compilation croisée; Luis, comment as-tu mis en place ton environnement croisé? –

Questions connexes