web-dev-qa-db-fra.com

Quel est le but de l'opcode nop?

Je passe par MSIL et je remarque qu'il y a beaucoup d'instructions nop . L'article MSDN indique qu'ils ne prennent aucune mesure et sont utilisés pour remplir l'espace si l'opcode est corrigé. Ils sont beaucoup plus utilisés dans les versions de débogage que dans les versions de version. Je sais que ces types d'instructions sont utilisés dans les langages d'assemblage pour s'assurer qu'un opcode tient sur une frontière Word, mais pourquoi est-il nécessaire dans MSIL?

79
Dan Goldstein

Les NOP ont plusieurs objectifs:

  • Ils permettent au débogueur de placer un point d'arrêt sur une ligne même s'il est combiné avec d'autres dans le code généré.
  • Il permet au chargeur de patcher un saut avec un décalage cible de taille différente.
  • Il permet à un bloc de code d'être aligné à une frontière particulière, ce qui peut être bon pour la mise en cache.
  • Il permet une liaison incrémentielle pour écraser des morceaux de code avec un appel à une nouvelle section sans avoir à se soucier de la taille globale de la fonction.
101
Anthony Williams

Voici comment les nops sont utilisés pour le débogage:

Les Nops sont utilisés par les compilateurs de langage (C #, VB, etc.) pour définir des points de séquence implicites. Ceux-ci indiquent au compilateur JIT où garantir que les instructions de la machine peuvent être mappées en arrière vers les instructions IL.

Entrée de blog de Rick Byer sur DebuggingModes.IgnoreSymbolStoreSequencePoints , explique quelques détails.

C # place également Nops après les instructions d'appel afin que l'emplacement du site de retour dans la source soit l'appel plutôt que la ligne après l'appel.

9
Steve Steiner

Il fournit une opportunité pour les marqueurs basés sur la ligne (par exemple, les points d'arrêt) dans le code où une version de construction n'en émettrait aucun.

8
harpo

Cela peut également accélérer l'exécution du code lors de l'optimisation pour des processeurs ou des architectures spécifiques:

Les processeurs utilisent depuis longtemps plusieurs pipelines qui fonctionnent à peu près en parallèle, de sorte que deux instructions indépendantes peuvent être extraites en même temps. Sur un processeur simple avec deux pipelines, le premier peut prendre en charge toutes les instructions, tandis que le second ne prend en charge qu'un sous-ensemble. De plus, il y a des blocages entre les pipelines quand il faut attendre le résultat d'une instruction précédente qui n'est pas encore terminée.

Dans ces circonstances, un nop dédié peut forcer l'instruction suivante dans un pipeline spécifique (le premier ou non le premier), et améliorer le couplage des instructions suivantes afin que le coût du nop est plus qu'amorti.

6
peterchen

Dans un processeur pour lequel j'ai travaillé récemment (pendant quatre ans), NOP a été utilisé pour s'assurer que l'opération précédente se terminait avant le démarrage de l'opération suivante. Par exemple:

charger la valeur à enregistrer (prend 8 cycles) nop 8 ajouter 1 à enregistrer

Cela a permis de s'assurer que le registre avait la valeur correcte avant l'opération d'ajout.

Une autre utilisation était de remplir des unités d'exécution, telles que les vecteurs d'interruption qui devaient être d'une certaine taille (32 octets) car l'adresse pour vector0 était, disons 0, pour le vecteur 1 0x20 et ainsi de suite, donc le compilateur y mettait des NOP si nécessaire.

4
Makis

Mec! No-op est génial! C'est une instruction qui ne fait que consommer du temps. Dans les âges sombres sombres, vous l'utiliseriez pour effectuer des micro-ajustements de synchronisation dans des boucles critiques ou, plus important encore, comme remplissage dans un code auto-modifiable.

4
plinth

Nop est essentiel dans la charge utile des exploits de dépassement de tampon.

3
ddaa

Comme l'a dit ddaa, nops vous permet de tenir compte de la variance dans la pile, de sorte que lorsque vous écrasez l'adresse de retour, il saute sur le traîneau nop (beaucoup de nops d'affilée), puis frappe correctement le code exécutable, plutôt que de sauter à certains octet dans l'instruction qui n'est pas le début.

3
Alex Gartrell

50 ans trop tard mais bon.

Les Nop sont utiles si vous tapez le code d'assemblage à la main. Si vous deviez supprimer du code, vous ne pourriez pas supprimer les anciens opcodes.

de même, vous pouvez insérer un nouveau code en écrasant un opcode et sauter ailleurs. Là, vous mettez les opcodes écrasés et insérez votre nouveau code. Lorsque vous êtes prêt, vous sautez en arrière.

Parfois, il fallait utiliser les outils disponibles. Dans certains cas, il s'agissait simplement d'un éditeur de code de machine très basique.

De nos jours avec les compilateurs, les techniques n'ont plus aucun sens.

3
Toad

Une utilisation classique pour eux est que votre débogueur puisse toujours associer une ligne de code source à une instruction IL.

3
Larry OBrien

Ils pourraient les utiliser pour prendre en charge modifier et continuer pendant le débogage. Il fournit au débogueur de l'espace pour travailler pour remplacer l'ancien code par un nouveau sans modifier les décalages, etc.

3
Rob Walker

J'ai également vu des NOP dans du code qui se modifie pour masquer ce qu'il fait en tant qu'espace réservé (veeery old copy protection).

2
TheMarko

Une utilisation quelque peu peu orthodoxe est NOP-Slides , utilisée dans les exploits de dépassement de tampon.

2
mdm

Dans la scène de craquage de logiciels, une méthode classique pour déverrouiller une application serait de patcher avec un NOP la ligne qui vérifie la clé ou l'enregistrement ou la période de temps ou autre afin qu'il ne fasse rien et continue simplement à démarrer l'application comme si elle était enregistrée .

2
shoosh

J'ai utilisé des NOP pour ajuster automatiquement la latence accumulée après avoir entré un ISR. Très pratique pour clouer le chronométrage à mort.

1
James Baker

Ils permettent à l'éditeur de liens de remplacer une instruction plus longue (généralement un saut en longueur) par une instruction plus courte (saut court). Le NOP prend l'espace supplémentaire - le code n'a pas pu être déplacé car cela empêcherait les autres sauts de fonctionner. Cela se produit au moment du lien, donc le compilateur ne peut pas savoir si un saut long ou court serait approprié.

Du moins, c'est l'une de leurs utilisations traditionnelles.

1
MarkR

Ce n'est pas une réponse à votre question spécifique, mais dans le passé, vous pouviez utiliser un NOP pour remplir un créneau de délai de branchement , si vous n'arriviez pas à le remplir avec une instruction autrement utile .

1
Chris Conway

Les compilateurs .NET alignent-ils la sortie MSIL? J'imagine que cela pourrait être utile pour accélérer l'accès à l'IL ... De plus, je crois comprendre qu'il est conçu pour être portable et que des accès alignés sont requis sur certaines autres plates-formes matérielles.

1
Brian Knoblauch

Le premier assemblage que j'ai appris était SPARC donc je connais le créneau de délai de branchement, si vous ne pouvez pas le remplir avec une autre instruction, généralement l'instruction que vous alliez mettre au-dessus de l'instruction de branchement ou incrémenter un compteur en boucles, vous utilisez un NOP.

Je ne suis pas familier avec le cracking, mais je pense qu'il est courant d'écraser la pile à l'aide de NOP, vous n'avez donc pas à calculer exactement où commence votre fonction malveillante.

1
Sunday