141 votes

Comment visualiser l'assemblage derrière le code en utilisant Visual C++ ?

Je lisais une autre question concernant l'efficacité de deux lignes de code, et le PO a dit qu'il avait regardé l'assemblage derrière le code et que les deux lignes étaient identiques en assemblage. Digression mise à part, comment pourrais-je voir le code d'assemblage créé lorsqu'un programme est compilé.

J'utilise le logiciel Visual C++ de Microsoft, mais j'aimerais également savoir s'il est possible de visualiser l'assemblage derrière un code écrit en Visual Basic.

Alors, comment puis-je voir le code assembleur derrière un programme écrit dans des langages de plus haut niveau comme C++ et Visual Basic ?

184voto

inazaruk Points 37760

Il existe plusieurs approches :

  1. Vous pouvez normalement voir le code d'assemblage lorsque vous déboguez du C++ dans Visual Studio (et Eclipse aussi). Pour cela, dans Visual Studio, mettez un point d'arrêt sur le code en question et lorsque le débogueur le trouve, cliquez sur "Go To Assembly" (ou appuyez sur CTRL+ALT+D).

  2. La deuxième approche consiste à générer des listes d'assemblage pendant la compilation. Pour cela, allez dans les paramètres du projet -> C/C++ -> Fichiers de sortie -> Emplacement de la liste ASM et indiquez le nom du fichier. Sélectionnez également "Assembly Output" pour "Assembly With Source Code".

  3. Compilez le programme et utilisez un débogueur tiers. Vous pouvez utiliser OllyDbg ou WinDbg pour cela. Vous pouvez également utiliser IDA (désassembleur interactif). Mais il s'agit là d'une façon très stricte de procéder.

33voto

steve Points 3500

Spécifiez le commutateur /FA pour le compilateur cl. Selon la valeur du commutateur, seul le code d'assemblage ou le code de haut niveau et le code d'assemblage sont intégrés. Le nom du fichier reçoit l'extension .asm. Voici les valeurs supportées :


  • /FA Code d'assemblage ; .asm
  • /FAc Code machine et assembleur ; .cod
  • /FAs Code source et code d'assemblage ; .asm
  • /FAcs Code machine, source et assemblage ; .cod

27voto

Vladimir Obrizan Points 1381

Note supplémentaire : il y a une grande différence entre la sortie de l'assembleur Debug et celle de Release. La première est utile pour apprendre comment le compilateur produit du code assembleur à partir de C++. La seconde permet d'apprendre comment le compilateur optimise les différentes constructions C++. Dans ce cas, certaines transformations C++ vers assembleur ne sont pas évidentes.

11voto

diapir Points 1017

Le moyen le plus simple est d'activer le débogueur et de vérifier l'état de l'ordinateur. fenêtre de démontage .

10voto

Peter Cordes Points 1375

La version précédente de cette réponse (un "hack" pour rextester.com) est en grande partie redondante maintenant que http://gcc.godbolt.org/ fournit CL 19 RC pour ARM, x86, et x86-64 (ciblant la convention d'appel de Windows, contrairement à gcc, clang, et icc sur ce site).

L'explorateur de compilateur Godbolt est conçu pour formater joliment la sortie asm du compilateur, en supprimant le "bruit" des directives, donc je recommande fortement de l'utiliser pour regarder l'asm des fonctions simples qui prennent des args et renvoient une valeur (afin qu'elles ne soient pas optimisées).

Pendant un certain temps, CL était disponible sur http://gcc.beta.godbolt.org/ mais pas sur le site principal, mais maintenant c'est sur les deux.


Pour obtenir la sortie asm de MSVC à partir de l'application http://rextester.com/l/cpp_online_compiler_visual compilateur en ligne : Ajouter /FAs aux options de la ligne de commande. Demandez à votre programme de trouver son propre chemin d'accès et de déterminer le chemin d'accès aux options de la ligne de commande. .asm et le jeter. Ou lancez un désassembleur sur le .exe .

par exemple http://rextester.com/OKI40941

#include <string>
#include <boost/filesystem.hpp>
#include <Windows.h>

using namespace std;

static string my_exe(void){
    char buf[MAX_PATH];
    DWORD tmp = GetModuleFileNameA( NULL, // self
                                  buf, MAX_PATH);
    return buf;
}

int main() {
    string dircmd = "dir ";
    boost::filesystem::path p( my_exe() );
    //boost::filesystem::path dir = p.parent_path();

    // transform c:\foo\bar\1234\a.exe 
    // into      c:\foo\bar\1234\1234.asm
    p.remove_filename();
    system ( (dircmd + p.string()).c_str() );

    auto subdir = p.end();      // pointing at one-past the end
    subdir--;                   // pointing at the last directory name
    p /= *subdir;               // append the last dir name as a filename
    p.replace_extension(".asm");
    system ( (string("type ") + p.string()).c_str() );
//    std::cout << "Hello, world!\n";
}

... code of functions you want to see the asm for goes here ...

type est la version DOS de cat . Je ne voulais pas inclure plus de code qui rendrait plus difficile la recherche des fonctions pour lesquelles je voulais voir l'asm. (Bien que l'utilisation de std::string et de boost aille à l'encontre de ces objectifs ! Quelques manipulations de chaînes de caractères de style C qui font plus d'hypothèses sur la chaîne qu'elles traitent (et ignorent la sécurité de la longueur maximale / l'allocation en utilisant un grand tampon) sur le résultat de GetModuleFileNameA serait bien moindre que le code machine total).

Je ne sais pas pourquoi, mais cout << p.string() << endl ne montre que le nom de base (c'est-à-dire le nom de fichier, sans les répertoires), même si l'impression de sa longueur montre qu'il ne s'agit pas seulement du nom nu. (Chromium48 sur Ubuntu 15.10). Il y a probablement un traitement de l'échappement de l'arrière-plan à un moment donné dans le fichier cout ou entre le stdout du programme et le navigateur web.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X