आपको gcc में C / C ++ स्रोत से कोडांतरक आउटपुट कैसे मिलेगा?


379

कोई इसे कैसे करता है?

अगर मैं यह विश्लेषण करना चाहता हूं कि कुछ कैसे संकलित हो रहा है, तो मुझे उत्सर्जित विधानसभा कोड कैसे मिलेगा?


8
एसएसएम आउटपुट को मानव पठनीय बनाने की युक्तियों के लिए , यह भी देखें: जीसीसी / क्लैंग असेंबली आउटपुट से "शोर" कैसे निकालें?
पीटर कॉर्डेस

जवाबों:


420

-SGcc (या g ++) के विकल्प का उपयोग करें ।

gcc -S helloworld.c

यह helloworld.c पर प्रीप्रोसेसर (सीपीपी) चलाएगा, प्रारंभिक संकलन का प्रदर्शन करेगा और फिर कोडांतरक चलाने से पहले रोक देगा।

डिफ़ॉल्ट रूप से यह एक फ़ाइल आउटपुट करेगा helloworld.s। आउटपुट फ़ाइल को -oविकल्प का उपयोग करके अभी भी सेट किया जा सकता है।

gcc -S -o my_asm_output.s helloworld.c

बेशक यह केवल तभी काम करता है जब आपके पास मूल स्रोत हो। एक विकल्प यदि आपके पास केवल परिणामी ऑब्जेक्ट फ़ाइल है objdump, --disassembleविकल्प सेट करके (या -dसंक्षिप्त रूप के लिए)।

objdump -S --disassemble helloworld > helloworld.dump

यह विकल्प सबसे अच्छा काम करता है यदि डिबगिंग विकल्प ऑब्जेक्ट फ़ाइल ( -gसंकलन समय पर) के लिए सक्षम है और फ़ाइल को छीन नहीं लिया गया है।

रनिंग file helloworldआपको विस्तार के स्तर तक कुछ संकेत देगा जो आपको objdump का उपयोग करके मिलेगा।


3
जबकि यह सही है, मैंने Cr McDonough के उत्तर के परिणामों को अधिक उपयोगी पाया।
Rhys Ulerich

3
एक अतिरिक्त उपयोग: objdump -M Intel -S --disassemble helloworld> helloworld.dump, बुद्धि सिंटैक्स में ऑब्जेक्ट डंप को लाइनक्स पर nasm के साथ संगत करने के लिए।
टचस्टोन

2
यदि आपके पास अनुकूलन / जांच करने के लिए एक ही कार्य है, तो आप ऑनलाइन इंटरएक्टिव C ++ कंपाइलर यानी गॉडबॉल्ट
fiorentinoing

1
@touchStone: गैस .intel_syntaxहै नहीं एनएएसएम के साथ संगत । यह MASM की तरह अधिक है (जैसे mov eax, symbolएक भार है, NASM के विपरीत जहां यह mov r32, imm32पते का है), लेकिन MASM के साथ पूरी तरह से संगत नहीं है। मैं इसे पढ़ने के लिए एक अच्छे प्रारूप के रूप में अत्यधिक अनुशंसा करता हूं, खासकर यदि आप NASM सिंटैक्स में लिखना पसंद करते हैं। objdump -drwC -Mintel | lessया gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | lessउपयोगी हैं। (यह भी देखें कि जीसीसी / क्लैंग असेंबली आउटपुट से "शोर" कैसे निकालना है? )। -masm=intelक्लैंग के साथ भी काम करता है।
पीटर कॉर्ड्स

3
बेहतर उपयोगgcc -O -fverbose-asm -S
9:17 बजे बेसाइल स्ट्राइनेकेविच सेप

172

यह सी कोड + लाइन नंबरों के साथ असेंबली कोड उत्पन्न करेगा, अधिक आसानी से यह देखने के लिए कि कौन सी लाइनें किस कोड को उत्पन्न करती हैं:

# create assembler code:
g++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst

प्रोग्रामर के लिए एल्गोरिदम में मिला , पेज 3 (जो पीडीएफ का कुल 15 वां पेज है)।


3
(यह वास्तव में पृष्ठ पर है (गिने हुए) 3 (जो कि पीडीएफ का 15 वां पृष्ठ है))
ग्रुमड्रिग

1
अफसोस की बात है कि asOS X पर ये झंडे नहीं हैं। यदि यह किया गया था, हालांकि, आप -Waविकल्पों को पास करने के लिए इसका उपयोग करके शायद एक-लाइन कर सकते हैं as
ग्रुमड्रिग

23
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lstइसका छोटा संस्करण होगा।
लीजेंड 2k

4
आप gcc -c -g -Wa,-ahl=test.s test.cया तो इस्तेमाल कर सकते हैं याgcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv

1
एक ब्लॉग पोस्ट ने इसे और अधिक विस्तार से समझाया, जिसमें किंवदंतियों और लु'यू जैसे एक-कमांड संस्करण शामिल थे। लेकिन क्यों -O0? यह उन भारों / भंडारों से भरा है जो किसी मूल्य को ट्रैक करना कठिन बनाते हैं, और अनुकूलित कोड कितना कुशल होगा, इसके बारे में आपको कुछ नहीं बताता है।
पीटर कॉर्ड्स

51

निम्नलिखित कमांड लाइन क्रिश्चियन गार्बिन के ब्लॉग से है

g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt

मैं विन + एक्सपी पर एक डॉस विंडो से जी ++ भागा, एक रूटीन के खिलाफ जिसमें एक निहित कास्ट है

c:\gpp_code>g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp: In function `int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'

आउटपुट को मूल C ++ कोड के साथ उत्पन्न कोड इटसेरस्पेंड किया गया है (C ++ कोड उत्पन्न asm स्ट्रीम में टिप्पणियों के रूप में दिखाया गया है)

  16:horton_ex2_05.cpp **** using std::setw;
  17:horton_ex2_05.cpp ****
  18:horton_ex2_05.cpp **** void disp_Time_Line (void);
  19:horton_ex2_05.cpp ****
  20:horton_ex2_05.cpp **** int main(void)
  21:horton_ex2_05.cpp **** {
 164                    %ebp
 165                            subl $128,%esp
?GAS LISTING C:\DOCUME~1\CRAIGM~1\LOCALS~1\Temp\ccx52rCc.s
166 0128 55                    call ___main
167 0129 89E5          .stabn 68,0,21,LM2-_main
168 012b 81EC8000      LM2:
168      0000
169 0131 E8000000      LBB2:
169      00
170                    .stabn 68,0,25,LM3-_main
171                    LM3:
172                            movl $0,-16(%ebp)

@Paladin - जरूरी नहीं। ओपी कोड / सी ++ स्रोत कोड के बराबर कोडांतरक आउटपुट प्राप्त करने के बारे में था, यह लिस्टिंग प्राप्त करता है, जो मैं मानता हूं कि कंपाइलर और ऑप्टिमाइज़र क्या कर रहा है यह समझने के लिए अधिक उपयोगी है। लेकिन यह असेंबलर को स्वयं को बर्फ़ बनाने का कारण बनता है, क्योंकि यह लाइन नंबरों की अपेक्षा नहीं कर रहा है, और विधानसभा निर्देशों के छोड़ दिया गया बाइट संकलित करता है।
जेसी चिशोल्म

कम से कम -O2, या जो भी अनुकूलन विकल्प आप वास्तव में अपने प्रोजेक्ट का निर्माण करते समय उपयोग करते हैं, यदि आप यह देखना चाहते हैं कि कैसे gcc आपके कोड का अनुकूलन करता है। (या यदि आप एलटीओ का उपयोग करते हैं, जैसे आपको करना चाहिए, तो आपको लिंकर आउटपुट को अलग करना होगा ताकि आप वास्तव में प्राप्त कर सकें।)
पीटर कॉर्ड्स

27

-S स्विच का उपयोग करें

g++ -S main.cpp

या जीसीसी के साथ भी

gcc -S main.c

यह भी देखें इस


7
अक्सर पूछे जाने वाले प्रश्न की जाँच करें: "यह आपके अपने प्रोग्रामिंग प्रश्न पूछने और उत्तर देने के लिए पूरी तरह से ठीक है"। बिंदु यह है कि अब StackOverflow दूसरों के लिए एक संसाधन के रूप में प्रश्नोत्तर शामिल है।
स्टीव जेसप

और हो सकता है कि कोई और आपके साथ आएगा और आपको बेहतर उत्तर देगा, हालांकि मेरा कभी-कभी थोड़ा वाचाल हो सकता है ...
PhirePhly

यहां तक ​​कि आपके खुद के प्रश्न बटन का जवाब भी है।
सिरो सेंटिल्ली 郝海东 冠状 iro i 法轮功 '

13

यदि आप जो देखना चाहते हैं, वह आउटपुट के लिंकिंग पर निर्भर करता है, तो आउटपुट ऑब्जेक्ट फ़ाइल / निष्पादन योग्य पर objdump उपरोक्त gcc -S के अतिरिक्त भी उपयोगी हो सकता है। यहाँ लोरेन मेरिट द्वारा एक बहुत ही उपयोगी स्क्रिप्ट है जो डिफ़ॉल्ट ओब्जेक्टम्प सिंटैक्स को अधिक पठनीय नस्म सिंटैक्स में परिवर्तित करती है:

#!/usr/bin/perl -w
$ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR ';
$reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])';
open FH, '-|', '/usr/bin/objdump', '-w', '-M', 'intel', @ARGV or die;
$prev = "";
while(<FH>){
    if(/$ptr/o) {
        s/$ptr(\[[^\[\]]+\],$reg)/$2/o or
        s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or
        s/$ptr/lc $1/oe;
    }
    if($prev =~ /\t(repz )?ret / and
       $_ =~ /\tnop |\txchg *ax,ax$/) {
       # drop this line
    } else {
       print $prev;
       $prev = $_;
    }
}
print $prev;
close FH;

मुझे संदेह है कि यह gcc -S के आउटपुट पर भी इस्तेमाल किया जा सकता है।


2
फिर भी, यह स्क्रिप्ट एक गंदी हैक है जो वाक्य रचना को पूरी तरह से परिवर्तित नहीं करती है। उदा mov eax,ds:0x804b794बहुत NASMish नहीं है। इसके अलावा, कभी-कभी यह केवल उपयोगी जानकारी को स्ट्रिप करता है: movzx eax,[edx+0x1]पाठक को यह अनुमान लगाने के लिए छोड़ देता है कि मेमोरी ऑपरेंड था byteया नहीं word
रुस्लान

पहले स्थान पर NASM सिंटैक्स में जुदा करने के लिए, Agner Fog's काobjconv उपयोग करें । आप इसे आउटपुट फ़ाइल = के साथ स्टडआउट करने के लिए इकट्ठा /dev/stdoutकर सकते हैं, ताकि आप lessदेखने के लिए पाइप कर सकें । वहाँ भी है ndisasm, लेकिन यह केवल फ्लैट बायनेरिज़ को अलग करता है, और ऑब्जेक्ट फ़ाइलों (ELF / PE) के बारे में नहीं जानता है।
पीटर कॉर्डेस

9

जैसा कि सभी ने बताया है, -SGCC के विकल्प का उपयोग करें । मैं यह भी जोड़ना चाहूंगा कि परिणाम भिन्न हो सकते हैं (बेतहाशा!) इस आधार पर कि आप अनुकूलन विकल्प जोड़ते हैं या नहीं ( -O0किसी के लिए भी, नहीं)-O2 एग्रेसिव ऑप्टिमाइज़ेशन के लिए)।

विशेष रूप से RISC आर्किटेक्चर पर, कंपाइलर अक्सर अनुकूलन करने में मान्यता से परे कोड को बदल देगा। परिणामों को देखने के लिए यह प्रभावशाली और आकर्षक है!


9

ठीक है, जैसा कि सभी ने कहा, -S विकल्प का उपयोग करें। यदि आप -save-temps विकल्प का उपयोग करते हैं, तो आप प्रीप्रोसेड फ़ाइल ( .i), असेंबली फ़ाइल ( .s) और ऑब्जेक्ट फ़ाइल (*। O) भी प्राप्त कर सकते हैं । (-E, -S, और -c का उपयोग करके उनमें से प्रत्येक को प्राप्त करें।)


8

जैसा कि पहले उल्लेख किया गया है, -S ध्वज को देखें।

यह झंडे के '-दंप-ट्री' परिवार को देखने के लायक है, विशेष रूप से '-fdump-tree-all', जो आपको gcc के कुछ मध्यवर्ती रूप देखने देता है। ये अक्सर कोडांतरक (कम से कम मेरे लिए) से अधिक पठनीय हो सकते हैं, और आपको देखते हैं कि अनुकूलन कैसे प्रदर्शन करता है।


8

यदि आप LLVM विधानसभा की तलाश कर रहे हैं:

llvm-gcc -emit-llvm -S hello.c

8

मुझे उत्तर के बीच यह संभावना दिखाई नहीं दे रही है, शायद इसलिए कि सवाल 2008 का है, लेकिन 2018 में आप मैट गोल्डबोल्ट की ऑनलाइन वेबसाइट का उपयोग कर सकते हैं https://godbolt.org

आप स्थानीय रूप से भी क्लोन क्लोन कर सकते हैं और अपनी परियोजना https://github.com/mattgodbolt/compiler-explorer चला सकते हैं


8

-save-temps

इसका उल्लेख https://stackoverflow.com/a/17083009/895245 पर किया गया था लेकिन मैं इसे और उदाहरण देता हूँ।

इस विकल्प का बड़ा लाभ खत्म हो गया -S है कि किसी भी बिल्ड स्क्रिप्ट में इसे जोड़ना बहुत आसान है, बिना बिल्ड में ज्यादा दखल दिए।

जब तुम करोगे:

gcc -save-temps -c -o main.o main.c

main.c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

और अब, सामान्य आउटपुट के अलावा main.o, वर्तमान कार्यशील निर्देशिका में निम्न फाइलें भी हैं:

  • main.i एक बोनस है और इसमें पूर्वनिर्मित फ़ाइल शामिल है:

    # 1 "main.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 31 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 32 "<command-line>" 2
    # 1 "main.c"
    
    
    int myfunc(int i) {
        return i + 1;
    }
  • main.s इसमें वांछित जनरेट विधानसभा शामिल है:

        .file   "main.c"
        .text
        .globl  myfunc
        .type   myfunc, @function
    myfunc:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   myfunc, .-myfunc
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
        .section    .note.GNU-stack,"",@progbits

यदि आप इसे बड़ी संख्या में फ़ाइलों के लिए करना चाहते हैं, तो इसके बजाय उपयोग करने पर विचार करें:

 -save-temps=obj

जो मध्यवर्ती फ़ाइलों को -oवर्तमान कार्य निर्देशिका के बजाय ऑब्जेक्ट आउटपुट के समान निर्देशिका में सहेजता है , इस प्रकार संभावित बेसनेम टकराव से बचा जाता है।

इस विकल्प के बारे में एक और अच्छी बात यह है कि यदि आप जोड़ते हैं -v:

gcc -save-temps -c -o main.o -v main.c

यह वास्तव में बदसूरत अस्थायी के बजाय उपयोग की जा रही स्पष्ट फाइलों को दिखाता है /tmp, इसलिए यह जानना आसान है कि क्या चल रहा है, जिसमें प्रीप्रोसेसिंग / संकलन / असेंबली चरण शामिल हैं:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

उबंटू में परीक्षण 19.04 amd64, GCC 8.3.0।




3

इन कमोड का उत्पादन

यहां आपके विंडोज पर किसी भी सी प्रोग्राम के असेंबली कोड को देखने / प्रिंट करने के चरण दिए गए हैं

कंसोल / टर्मिनल / कमांड प्रॉम्प्ट:

  1. सी कोड एडिटर में सी प्रोग्राम को कोडब्लॉक की तरह लिखें और एक्स्टेंशन .c से सेव करें

  2. इसे संकलित करें और चलाएं।

  3. एक बार सफलतापूर्वक चलाने के बाद, उस फ़ोल्डर पर जाएं जहां आपने अपना gcc संकलक स्थापित किया है और इसे दे

    '.c' फ़ाइल की '.s' फ़ाइल प्राप्त करने के लिए निम्नलिखित कमांड

    C: \ gcc> gcc -S पूर्ण पथ C फ़ाइल ENTER की

    एक उदाहरण कमांड (मेरे मामले में)

    C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c

    यह '.s' फ़ाइल की 'मूल .c' फ़ाइल को आउटपुट करता है

४। इसके बाद, निम्न कमांड टाइप करें

C; \ gcc> cpp filename.s ENTER

उदाहरण कमांड (मेरे मामले में)

C; \ gcc> cpp alternate_letters.s

यह आपके C प्रोग्राम की संपूर्ण असेंबली भाषा कोड को प्रिंट / आउटपुट करेगा।


2

एक विकल्प के रूप में "-S" का उपयोग करें। यह टर्मिनल में असेंबली आउटपुट प्रदर्शित करता है।


टर्मिनल में प्रदर्शित करने के लिए, उपयोग करें gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less-Sअपने स्वयं के निर्माण पर foo.s
पीटर कॉर्डेस

2

हाल ही में मैं एक कार्यक्रम में प्रत्येक फ़ंक्शन की असेंबली जानना चाहता
था कि यह मैंने कैसे किया।

$ gcc main.c                      // main.c source file
$ gdb a.exe                       // gdb a.out in linux
  (gdb) disass main               // note here main is a function
                                  // similary it can be done for other functions

2

यहाँ gcc का उपयोग करके C के लिए एक समाधान दिया गया है:

gcc -S program.c && gcc program.c -o output
  1. यहां पहला भाग प्रोग्राम के असेंबली आउटपुट को प्रोग्राम के समान फ़ाइल नाम में संग्रहीत करता है, लेकिन बदले हुए .s एक्सटेंशन के साथ, आप इसे किसी भी सामान्य टेक्स्ट फ़ाइल के रूप में खोल सकते हैं।

  2. यहां दूसरा भाग आपके प्रोग्राम को वास्तविक उपयोग के लिए संकलित करता है और एक निर्दिष्ट फ़ाइल नाम के साथ आपके प्रोग्राम के लिए एक निष्पादन योग्य बनाता है।

ऊपर इस्तेमाल किया जाने वाला program.c आपके प्रोग्राम का नाम है और आउटपुट उस निष्पादन योग्य का नाम है जिसे आप उत्पन्न करना चाहते हैं।

BTW यह StackOverFlow पर मेरी पहली पोस्ट है: -}

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