Visual C ++ kullanarak kodun arkasındaki derlemeyi nasıl görüntüleyebilirim?


117

İki satır kodun verimliliğiyle ilgili başka bir soru okuyordum ve OP, kodun arkasındaki montaja baktığını ve her iki satırın da montajda aynı olduğunu söyledi. Özet bir yana, bir program derlendiğinde oluşturulan montaj kodunu nasıl görebilirim.

Microsoft'un Visual C ++ 'sını kullanıyorum, ancak Visual Basic'te yazılmış kodun arkasındaki derlemeyi görüntülemenin mümkün olup olmadığını da bilmek istiyorum.

Öyleyse, C ++ ve Visual Basic gibi daha yüksek seviyeli dillerde yazılmış bir programın arkasındaki derleme kodunu nasıl görebilirim?


Diğerlerinin daha önce de belirttiği gibi msvc'de montaj listesi olarak adlandırılır. Bu sıkıcı adımları otomatikleştirmek için düzenleyici bağlam menüsüne girişler ekleyen basit bir eklenti oluşturdum: marketplace.visualstudio.com/items?itemName=Trass3r.DevUtils
Trass3r

Yanıtlar:


149

Birkaç yaklaşım var:

  1. Visual Studio'da C ++ hata ayıklaması yaparken (ve tutulması da) normalde montaj kodunu görebilirsiniz. Bunun için Visual Studio'da söz konusu koda bir kesme noktası koyun ve hata ayıklayıcı ona ulaştığında sağ tıklayın ve "Derlemeye Git" i bulun (veya CTRL + ALT + D tuşlarına basın)

  2. İkinci yaklaşım, derleme sırasında derleme listeleri oluşturmaktır. Bunun için proje ayarlarına gidin -> C / C ++ -> Çıktı Dosyaları -> ASM Liste Konumu ve dosya adını girin. Ayrıca, "Kaynak Kodlu Montaj" için "Montaj Çıkışı" nı seçin.

  3. Programı derleyin ve herhangi bir üçüncü taraf hata ayıklayıcıyı kullanın. Bunun için OllyDbg veya WinDbg kullanabilirsiniz. Ayrıca IDA (etkileşimli ayırıcı) kullanabilirsiniz. Ama bunu yapmanın sert yolu bu.


5
Tüm program optimizasyonu etkinken (en azından VS2010'da) statik bir kitaplığı derlerken 2 numaralı yaklaşımın işe yaramadığını unutmayın. Bu mantıklı - derleyici henüz son kodu oluşturmadı.
dhaffey

3
Visual Studio 2017'de "Goto Disassembly" olarak adlandırılır
Matthias

2. yaklaşımla montajı nasıl görebilirim?
user1507435

Varsayılan konumu kullandıysanız, hata ayıklama dizininde bir .asm dosyası görmelisiniz.
user3015682

28

Ek not: Debug assembler çıktısı ile Release one arasında büyük fark vardır. Birincisi, derleyicinin C ++ 'dan nasıl assembler kodu ürettiğini öğrenmek iyidir. İkincisi, derleyicinin çeşitli C ++ yapılarını nasıl optimize ettiğini öğrenmek için iyidir. Bu durumda bazı C ++ - asm dönüşümleri açık değildir.


Hata Ayıklama yürütülebilir dosyasını sökerken, çalışırken kodun paketini açtığını fark ettim, bunun Yayın sürümünde gerçekleşmediğini fark ettim. Ayrıca her ikisini de PEiD ile açarken sadece Hata Ayıklama sürümü "Microsoft Visual C ++ 8.0 [Hata Ayıklama]" gösterir.
jyz

9
Bu kesinlikle doğrudur. Ama soruya hiç cevap vermiyor.
imallett

25

Cl derleyicisi için / FA anahtarını belirtin. Anahtarın değerine bağlı olarak ya sadece montaj kodu ya da üst düzey kod ve montaj kodu entegre edilmiştir. Dosya adı .asm dosya uzantısını alır. Desteklenen değerler şunlardır:


  • / FA Montaj kodu; .asm
  • / FAc Makine ve montaj kodu; .Morina
  • / FA'lar Kaynak ve montaj kodu; .asm
  • / FAcs Makine, kaynak ve montaj kodu; .Morina

10

En kolay yol, hata ayıklayıcıyı çalıştırmak ve sökme penceresini kontrol etmektir .


8

Bu cevabın önceki sürümü (rextester.com için bir "hack"), http://gcc.godbolt.org/ ARM, x86 ve x86-64 için CL 19 RC sağladığından (Windows arama kuralını hedefleyen , o sitedeki gcc, clang ve icc'den farklı olarak).

Godbolt derleyici gezgini, derleyici asm çıktısını güzel bir şekilde biçimlendirmek ve yönergelerin "gürültüsünü" kaldırmak için tasarlanmıştır; bu nedenle, args alan ve bir değer döndüren basit işlevler için asm'ye bakmak için onu kullanmanızı şiddetle tavsiye ederim (bu nedenle optimize edilmiş).

Bir süredir, CL http://gcc.beta.godbolt.org/ adresinde mevcuttu, ancak ana sitede bulunmuyordu, ancak şimdi her ikisinde de bulunuyor.


MSVC asm çıktısını almak için http://rextester.com/l/cpp_online_compiler_visual çevrimiçi derleyici: Ekle /FAskomut satırı seçeneklerine. Programınızın kendi yolunu bulmasını ve bu yolu bulup .asmonu terk etmesini sağlayın . Veya üzerinde bir sökücü çalıştırın .exe.

örneğin 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 ...

typeDOS sürümüdür cat. Asm'i görmek istediğim işlevleri bulmayı zorlaştıracak daha fazla kod eklemek istemedim. (Bu hedeflere giden std :: string ve boost çalıştırmak sayacı kullanılarak rağmen! İşlenmesi (ve oluyor dize hakkında daha varsayımlarda bulunur Bazı C tarzı dize manipülasyon sonucu üzerine) büyük bir tampon kullanarak maksimum uzunlukta güvenlik / tahsisini yok sayar GetModuleFileNameAmisiniz? Öğesinin toplam makine kodu çok daha az olacaktır.)

IDK neden, ancak cout << p.string() << endlyalnızca temel adını gösterir (yani dosya adı, dizinler olmadan), uzunluğunu yazdırmak bunun yalnızca çıplak ad olmadığını gösterse de. (Ubuntu 15.10'da Chromium48). Muhtemelen bir noktada coutveya programın stdout'u ile web tarayıcısı arasında bir miktar ters eğik çizgi kaçış işlemi vardır .


@MichaelPetch: ah, dönüşler ortaya olduğu Denedim ne olduğunu. .c_str()işaretçi gibi görünen şeyi yazdırır. Bağlantıyı izlerseniz, hexdump a std::string(ile devre dışı bırakılmış #if 0) kodunu göreceksiniz . Dizenin iyi olduğu, ancak coutweb tarayıcısına ulaşmadığı ortaya çıktı . Ascii olmayan karakterler de yok, sadece ters eğik çizgiler.
Peter Cordes

Bir şey eksik olabilir ama ne zaman subdir--; p /= *subdir;sen azaltmak vermedi p sadece dosya adına? Ya da belki yazdırmaya çalıştığınız şeyi yanlış anlıyorum.
Michael Petch

Ben oldukça anlamıyorum tahmin subdir--izledi p /= *subdirzaman subdiraslenp.end()
Michael Petch

@MichaelPetch: güncellenmiş yorumlar. Dosya adı olarak kullanmak için yolun son dizin bileşenini almam gerekiyordu. İşe yarıyor, ama halletmem uzun zamanımı aldı çünkü GetModuleFileNameAsadece geri döndüğümü düşündüm a.exe. Onu altlık döküp çalıştığını bildiğim uzunluğu yazdırana kadar değildi ve programın yolu değiştirmesini sağlayabilirdim, sadece yolu yazdıramazdım
Peter Cordes

1
Evet, web tarayıcısı için işlerken kötü bir şekilde çevrilen dosya adının \\r( \rderleyici çıktı verdiği zaman) parçası gibi görünüyor . Kullanılması p.generic_string()işleri ancak ters eğik çizgiler düz eğik çizgi vardır.
Michael Petch

5

Visual C ++ 'da proje seçenekleri, inanıyorum ki Çıktı Dosyaları ASM listesinin kaynak koduyla çıktısını almak için bir seçeneğe sahiptir. Böylece, C / C ++ kaynak kodunu ve sonuçta ortaya çıkan ASM'yi aynı dosyada göreceksiniz.


5

MSVC için bağlayıcıyı kullanabilirsiniz.

link.exe / döküm / keten numaraları / disasm /out:foo.dis foo.dll

foo.pdb'nin sembolleri almak için mevcut olması gerekir


1

Red Gate'in .NET Reflektörü bana birkaç defadan fazla yardımcı olan oldukça harika bir araçtır. Bu yardımcı programın size MSIL'i kolayca göstermenin dışındaki artı tarafı, birçok üçüncü taraf DLL'yi analiz edebilmeniz ve Reflektörün MSIL'i C # ve VB'ye dönüştürmesini sağlayabilmenizdir.

Kodun kaynak kadar net olacağına söz vermiyorum ama onu takip etmekte çok fazla sorun yaşamazsınız.


2
Not: Yalnızca yönetilen montajlar için geçerlidir, montajcıdaki gibi demontaj için değil, asm.
sean e

İyi bir nokta, "iki satır kodun montajda aynı olması" yerine "kodun iki satırı aynı mı?" Şeklinde okudum
Dave L

Yalnızca dotnet uygulamalarında çalışır, Visual C ++ bağlayıcı veya derleyicide değil.
Muhammed Ali

1

Montaj kodunu görmek için hata ayıklamadan bahsediyorsanız, en kolay yol Debug-> Windows-> Disassembly (veya Alt-8) 'dir. Bu, çağrılan bir işleve girmenize ve Sökme'de kalmanıza izin verecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.