Maison >développement back-end >C++ >Pourquoi l'utilisation du pointeur de base (%rbp) dans l'assemblage en ligne C provoque-t-elle des défauts de segment ?

Pourquoi l'utilisation du pointeur de base (%rbp) dans l'assemblage en ligne C provoque-t-elle des défauts de segment ?

Linda Hamilton
Linda Hamiltonoriginal
2025-01-01 07:57:14729parcourir

Why Does Using the Base Pointer (%rbp) in C   Inline Assembly Cause Segfaults?

Problème : Utilisation du registre de pointeur de base (%rbp) dans un assemblage en ligne C

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.

Explication

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.

Solution

Il existe trois solutions principales à ce problème :

  1. Utilisez un opérande de sortie « mémoire » (tel qu'un tableau de travail) pour l'espace de travail et ne le lisez pas.
  2. Sauter la zone rouge en utilisant add $-128, %rsp / sub $-128, %rsp autour du code assembleur.
  3. Compilez avec -mno-red-zone (mais notez qu'il ne s'agit pas d'une option par fonction).

Approche alternative

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn