Lors de l'utilisation d'un assemblage en ligne pour accéder au registre de pointeur de base (%rbp) dans un C fonction, une erreur de segmentation inattendue se produit après l'accès au argument.
Le problème réside dans le fait de marcher sur la "zone rouge" située sous RSP (ou pointeur de soustraction), qui stocke les valeurs dont GCC doit garder la trace. Dans l'exemple de code fourni, une instruction push est utilisée dans l'assembly en ligne, qui décrémente %rsp de 8 et écrase les 32 bits inférieurs de l'argument de la fonction (&x).
Lorsque l'assembly en ligne est terminé, GCC tente d'utiliser la valeur écrasée comme adresse pour un magasin de 4 octets, conduisant au segment défaut.
Il existe trois solutions principales à ce problème :
Au lieu d'utiliser un dépassement de zone rouge, envisagez d'allouer explicitement un espace de travail au sein de l'assembly en ligne à l'aide d'une contrainte "=m", comme le montre le code corrigé suivant exemple :
void Bar(int &x) { int tmp; long tmplong; asm ("lea -16 + %[mem1], %%rbp\n\t" "imul , %%rbp, %q[reg1]\n\t" // q modifier: 64bit name. "add %k[reg1], %k[reg1]\n\t" // k modifier: 32bit name "movl , %[mem1]\n\t" // some asm instruction writing to mem : [mem1] "=m" (tmp), [reg1] "=r" (tmplong) : : "%rbp" ); x = 5; }
Ici, la contrainte "=m" garantit que l'espace de travail est alloué dans la zone rouge et évite d'écraser l'argument de la fonction.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!