विज़ुअल C ++ का उपयोग करके कोड के पीछे असेंबली कैसे देखें?


117

मैं कोड की दो लाइनों की दक्षता से संबंधित एक और प्रश्न पढ़ रहा था, और ओपी ने कहा कि उन्होंने कोड के पीछे विधानसभा को देखा और दोनों लाइनें विधानसभा में समान थीं। एक तरफ डिग्रेशन, एक प्रोग्राम संकलित होने पर मैं असेंबली कोड को कैसे देख सकता था।

मैं Microsoft के Visual C ++ का उपयोग कर रहा हूं, लेकिन मैं यह भी जानना चाहूंगा कि क्या Visual Basic में लिखे कोड के पीछे असेंबली को देखना संभव है।

तो, मैं C ++ और विजुअल बेसिक जैसी उच्च स्तरीय भाषाओं में लिखे गए प्रोग्राम के पीछे असेंबली कोड कैसे देख सकता हूं?


इसे msvc में असेंबली लिस्टिंग कहा जाता है क्योंकि अन्य लोगों ने पहले ही उल्लेख किया है। मैंने उन थकाऊ चरणों को स्वचालित करने के लिए संपादक संदर्भ मेनू में प्रविष्टियों को जोड़ते हुए एक सरल प्लगइन बनाया: marketplace.visualstudio.com/items?itemName=Trass3r.DevUtils
Trass3r

जवाबों:


149

कई दृष्टिकोण हैं:

  1. दृश्य स्टूडियो (और ग्रहण भी) में C ++ डिबग करते समय आप आम तौर पर असेंबली कोड देख सकते हैं। इसके लिए विजुअल स्टूडियो ने प्रश्न में कोड पर एक ब्रेकपॉइंट लगाया और जब डिबगर ने इसे कठोर क्लिक किया और "गो टू असेंबली" खोजें (या CTRL + ALT + D दबाएं)

  2. दूसरा दृष्टिकोण संकलन करते समय विधानसभा लिस्टिंग उत्पन्न करना है। इसके लिए प्रोजेक्ट सेटिंग्स -> C / C ++ -> आउटपुट फाइल्स -> ASM लिस्ट लोकेशन पर जाएं और फाइल नेम भरें। "असेंबली आउटपुट" को "असेंबली विद सोर्स कोड" भी चुनें।

  3. प्रोग्राम को संकलित करें और किसी भी तृतीय-पक्ष डिबगर का उपयोग करें। इसके लिए आप OllyDbg या WinDbg का उपयोग कर सकते हैं। इसके अलावा आप आईडीए (इंटरएक्टिव डिस्सेम्बलर) का उपयोग कर सकते हैं। लेकिन ऐसा करने का यह कट्टर तरीका है।


5
ध्यान दें कि # 2 पूरे प्रोग्राम ऑप्टिमाइज़ेशन (सक्षम VS2010 में कम से कम) के साथ एक स्थिर लाइब्रेरी को संकलित करते समय काम नहीं करता है। जो समझ में आता है - कंपाइलर ने अभी तक अंतिम कोड नहीं बनाया है।
dhaffey

3
इसे विजुअल स्टूडियो 2017 में "गोटो डिसएस्पैम्स" कहा जाता है
मैथियास

# 2 दृष्टिकोण के साथ, मैं विधानसभा कैसे देख सकता हूं?
user1507435

यदि आपने डिफ़ॉल्ट स्थान का उपयोग किया है, तो डीबग डिर में एक .asm फ़ाइल देखनी चाहिए।
user3015682

28

अतिरिक्त नोट: डिबग असेंबलर आउटपुट और रिलीज़ एक के बीच बड़ा अंतर है। पहला सीखने के लिए अच्छा है कि कंपाइलर C ++ से कोडांतरक कोड कैसे तैयार करता है। दूसरा सीखना अच्छा है कि कंपाइलर विभिन्न C ++ कंस्ट्रक्शन को कैसे अनुकूलित करता है। इस मामले में कुछ C ++ - to-asm ट्रांसफ़ॉर्मेशन स्पष्ट नहीं हैं।


मैंने देखा कि डिबग निष्पादन योग्य को अलग करते समय यह कोड को अनपैक करते समय लगता है कि यह चल रहा है, यह रिलीज संस्करण पर नहीं होता है। PEID के साथ दोनों को खोलने पर भी केवल डीबग संस्करण "Microsoft Visual C ++ 8.0 [डीबग]" दिखाता है।
jyz

9
यह बिल्कुल सच है। लेकिन यह इस सवाल का जवाब नहीं देता है।
imallett

25

Cl कंपाइलर के लिए / FA स्विच निर्दिष्ट करें। स्विच के मूल्य के आधार पर या तो केवल विधानसभा कोड या उच्च-स्तरीय कोड और विधानसभा कोड एकीकृत होता है। फ़ाइल नाम को .asm फ़ाइल एक्सटेंशन मिलता है। यहाँ समर्थित मूल्य हैं:


  • / एफए विधानसभा कोड; .asm
  • / एफएसी मशीन और विधानसभा कोड; .cod
  • / एफए स्रोत और विधानसभा कोड; .asm
  • / FAcs मशीन, स्रोत और विधानसभा कोड; .cod

10

सबसे आसान तरीका डिबगर को फायर करना और डिस्सैम्ड विंडो को चेक करना है


8

इस उत्तर के पहले संस्करण (rextester.com के लिए एक "हैक") अब ज्यादातर बेमानी है कि http://gcc.godbolt.org/ सीएल 19 आरसी प्रदान करता है एआरएम, x86 और x86-64 के लिए (Windows कॉलिंग कन्वेंशन को लक्षित करते हुए) , gcc, clang, और उस साइट पर icc के विपरीत)।

Godbolt कंपाइलर एक्सप्लोरर अच्छी तरह से संकलक एसएम आउटपुट के लिए डिज़ाइन किया गया है, निर्देशों के "शोर" को हटा रहा है, इसलिए मैं अत्यधिक उपयोग करने वाले साधारण कार्यों के लिए एएसएम को देखने के लिए इसका उपयोग करने की सलाह देता हूं जो कि args लेते हैं और एक मान लौटाते हैं (इसलिए वे नहीं होंगे अनुकूलित)।

कुछ समय के लिए, सीएल http://gcc.beta.godbolt.org/ पर उपलब्ध था , लेकिन मुख्य साइट नहीं थी, लेकिन अब यह दोनों पर है।


Http://rextester.com/l/cpp_online_compiler_visual ऑनलाइन कंपाइलर से MSVC asm आउटपुट प्राप्त करने के लिए : /FAsकमांड लाइन विकल्पों में जोड़ें । अपने कार्यक्रम के लिए अपना रास्ता खोजें और बाहर के लिए काम करते हैं.asm और उसे डंप कर रहे हैं। या पर एक disassembler चलाते हैं .exe

जैसे 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 का डॉस संस्करण है cat । मैं और अधिक कोड शामिल नहीं करना चाहता था, जिससे मुझे उन कार्यों को खोजने में मुश्किल हो, जिनके लिए मैं asm देखना चाहता था। (हालांकि std :: string और बूस्ट रन काउंटर का उपयोग उन लक्ष्यों के लिए किया जाता है! कुछ C- शैली स्ट्रिंग हेरफेर जो कि इसके प्रसंस्करण के लिए स्ट्रिंग के बारे में अधिक धारणा बनाता है (और एक बड़े बफर का उपयोग करके अधिकतम-लंबाई सुरक्षा / आवंटन की उपेक्षा करता है)GetModuleFileNameA चाहेंगे बहुत कम कुल मशीन कोड हो।)

IDK क्यों, लेकिन cout << p.string() << endlकेवल बेसनेम (यानी निर्देशिका के बिना फ़ाइल नाम) दिखाता है, भले ही इसकी लंबाई को मुद्रित करना दिखाता है कि यह सिर्फ नंगे नाम नहीं है। (Ubuntu 15.10 पर क्रोमियम 48)। coutप्रोग्राम के स्टडआउट और वेब ब्राउजर के बीच कुछ बिंदु पर कुछ बैकस्लैश-एस्केप प्रोसेसिंग है।


@ मिचेल पेपर: ओह, यह पता चला है कि मैंने क्या कोशिश की थी। .c_str()एक सूचक की तरह दिखता है प्रिंट। यदि आप लिंक का अनुसरण करते हैं, तो आपको कोड को हेक्सडंप std::string( एक साथ अक्षम #if 0) दिखाई देगा। यह पता चला है कि स्ट्रिंग ठीक है, लेकिन coutयह वेब ब्राउज़र को नहीं मिल रहा है। किसी भी गैर-अस्सी के पात्र नहीं हैं, बस बैकस्लैश।
पीटर कॉर्ड्स

मुझे कुछ याद आ रहा है, लेकिन जब आपने पी को केवल फ़ाइल नाम के लिए subdir--; p /= *subdir;कम नहीं किया था ? या हो सकता है कि मैं गलत समझ रहा हूं कि आप क्या छापना चाह रहे हैं।
माइकल पेट

मुझे लगता है कि मैं मूल रूप से subdir--उसके बाद समझ में नहीं आया p /= *subdirजबsubdirp.end()
माइकल पेट

@MichaelPetch: अपडेट की गई टिप्पणियां। मुझे फ़ाइल नाम के रूप में उपयोग करने के लिए पथ के अंतिम निर्देशिका घटक को प्राप्त करने की आवश्यकता थी। यह काम करता है, लेकिन मुझे बाहर काम करने के लिए एक लंबा समय लगा क्योंकि मुझे लगा GetModuleFileNameAकि बस लौट रही थी a.exe। यह तब तक नहीं था जब तक कि मैं इसे बढ़ा-चढ़ा कर नहीं लिखता था और मुझे पता था कि यह काम कर रहा है, और मैं इस पथ को हेरफेर कर सकता हूं, मैं सिर्फ पथ प्रिंट नहीं कर सका
पीटर कॉर्ड

1
हाँ, ऐसा लगता है \\r(अच्छी तरह से \rजब कंपाइलर इसे आउटपुट करता है) फ़ाइल नाम का वह हिस्सा जो वेब ब्राउज़र के लिए रेंडर करते समय खराब तरीके से अनुवादित होता है। p.generic_string()कार्यों का उपयोग करते हुए लेकिन बैकस्लैश आगे के स्लैश हैं।
माइकल पेट

5

दृश्य C ++ में प्रोजेक्ट विकल्प के तहत, आउटपुट फ़ाइलें मेरा मानना ​​है कि सोर्स कोड के साथ ASM लिस्टिंग आउटपुट के लिए एक विकल्प है। तो आपको C / C ++ सोर्स कोड और परिणामस्वरूप ASM सभी एक ही फाइल में दिखाई देंगे।


5

MSVC के लिए आप लिंकर का उपयोग कर सकते हैं।

link.exe / डंप / लिनेनट / डिसमिस / आउट :foo.dis foo.dll

प्रतीकों को प्राप्त करने के लिए foo.pdb उपलब्ध होना चाहिए


1

रेड गेट के .NET रिफ्लेक्टर एक बहुत ही बढ़िया उपकरण है जिसने मुझे कुछ समय से अधिक समय तक मदद की है। आसानी से आपको एमएसआईएल दिखाने के बाहर इस उपयोगिता का प्लस पक्ष यह है कि आप बहुत सारे तृतीय-पक्ष डीएलएल का विश्लेषण कर सकते हैं और रिफ्लेक्टर को एमएसआईएल को सी # और वीबी में परिवर्तित करने का ध्यान रखते हैं।

मैं वादा नहीं कर रहा हूं कि कोड स्रोत के रूप में स्पष्ट होगा लेकिन आपको इसके बाद बहुत परेशानी नहीं होनी चाहिए।


2
नोट: केवल असेंबल किए गए असेंबलियों पर ही लागू होता है जैसे कि असेंबलर, एसएसएम में डिसाइड करने के लिए नहीं।
सीन ई

अच्छी बात है, मैंने इसे "असेंबली में कोड की दो पंक्तियाँ हैं" के बजाय "असेंबली में कोड की दो पंक्तियाँ समान हैं" के रूप में पढ़ा
डेव एल

यह केवल डॉटनेट एप्स पर काम करेगा, न कि विजुअल C ++ लिंकर या कंपाइलर पर।
मुहम्मद अली

1

यदि आप असेंबली कोड देखने के लिए डिबगिंग के बारे में बात कर रहे हैं, तो सबसे आसान तरीका डिबग है-> विंडोज-> डिसएस्पेशन (या Alt-8)। यह आपको एक कॉल किए गए फ़ंक्शन में जाने देगा और Disassembly में रहेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.