كيف يمكنك الحصول على مخرجات المجمع من مصدر C/C++ في دول مجلس التعاون الخليجي؟

StackOverflow https://stackoverflow.com/questions/137038

سؤال

كيف واحد يفعل هذا؟

إذا كنت أرغب في تحليل كيفية تجميع شيء ما، فكيف يمكنني الحصول على رمز التجميع المنبعث؟

هل كانت مفيدة؟

المحلول

استخدم ال -S خيار دول مجلس التعاون الخليجي (أو g++).

gcc -S helloworld.c

سيؤدي هذا إلى تشغيل المعالج المسبق (cpp) عبر 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.

نصائح أخرى

سيؤدي هذا إلى إنشاء رمز asm مع رمز C + أرقام الأسطر المتشابكة لمعرفة الخطوط التي تولد أي رمز بسهولة أكبر.

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

عثر عليه في خوارزميات للمبرمجين, ، الصفحة 3 (وهي الصفحة الخامسة عشرة الإجمالية لملف PDF).

سطر الأوامر التالي من مدونة كريستيان جاربين

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

لقد قمت بتشغيل G++ من نافذة DOS على نظام Win-XP، مقابل روتين يحتوي على طاقم ضمني

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)

استخدم رمز التبديل -S

g++ -S main.cpp

أو أيضًا مع دول مجلس التعاون الخليجي

gcc -S main.c

انظر أيضا هذا

إذا كان ما تريد رؤيته يعتمد على ربط الإخراج، فقد يكون objdump على ملف كائن الإخراج/القابل للتنفيذ مفيدًا أيضًا بالإضافة إلى gcc -S المذكور أعلاه.إليك نصًا مفيدًا جدًا من تأليف Loren Merritt يقوم بتحويل صيغة objdump الافتراضية إلى صيغة nasm الأكثر قابلية للقراءة:

#!/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.

حسنًا، كما قال الجميع، استخدم الخيار -S.إذا كنت تستخدم الخيار -save-temps، فيمكنك أيضًا الحصول على ملف تمت معالجته مسبقًا(.i)، ملف التجميع (.s) وملف الكائن (*.o).(احصل على كل واحد منهم باستخدام -E، -S، و -c.)

كما أشار الجميع، استخدم -S خيار لدول مجلس التعاون الخليجي.أود أيضًا أن أضيف أن النتائج قد تختلف (بشكل كبير!) اعتمادًا على ما إذا كنت تضيف خيارات التحسين أم لا (-O0 من أجل لا شيء، -O2 للتحسين العدواني).

في معماريات RISC على وجه الخصوص، غالبًا ما يقوم المترجم بتحويل التعليمات البرمجية إلى ما هو أبعد من التعرف عليه أثناء إجراء التحسين.إنه أمر مثير للإعجاب ورائع أن ننظر إلى النتائج!

كما ذكرنا سابقًا، انظر إلى علامة -S.

من المفيد أيضًا النظر إلى مجموعة أعلام "-fdump-tree"، وبالأخص "-fdump-tree-all"، والتي تتيح لك رؤية بعض الأشكال الوسيطة لدول مجلس التعاون الخليجي.غالبًا ما تكون هذه أكثر قابلية للقراءة من المجمّع (على الأقل بالنسبة لي)، وتتيح لك رؤية كيفية أداء تمريرات التحسين.

استخدم الخيار -S:

gcc -S program.c

إذا كنت تبحث عن تجميع LLVM:

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

لا أرى هذا الاحتمال بين الإجابات، ربما لأن السؤال من عام 2008، لكن في عام 2018 يمكنك استخدام موقع Matt Goldbolt على الإنترنت https://godbolt.org

يمكنك أيضًا استنساخ git محليًا وتشغيل مشروعه https://github.com/mattgodbolt/compiler-explorer

من: http://www.delorie.com/djgpp/v2faq/faq8_20.html

gcc -c -g -Wa,-a,-ad [خيارات دول مجلس التعاون الخليجي الأخرى] foo.c > foo.lst

في بديل عن إجابة Phirephly أو مجرد استخدام -s كما قال الجميع.

Output of these commnads

فيما يلي خطوات رؤية/طباعة رمز التجميع لأي برنامج C على نظام Windows الخاص بك

وحدة التحكم/المحطة/موجه الأوامر:

  1. اكتب برنامج C في محرر أكواد C مثل كتل التعليمات البرمجية واحفظه بامتداد .c

  2. تجميعها وتشغيلها.

  3. بمجرد التشغيل بنجاح، انتقل إلى المجلد الذي قمت بتثبيت برنامج التحويل البرمجي gcc الخاص بك فيه وقم بإعطاء الملف

    الأمر التالي للحصول على ملف ".s" من الملف ".c".

    C:\ gcc> gcc -S المسار الكامل لملف C ENTER

    أمر مثال (كما في حالتي)

    C:\gcc> gcc -S D:\Aa_C_Certified\alternate_letters.c

    يؤدي هذا إلى إخراج ملف ".s" من الملف ".c" الأصلي

4 .بعد هذا اكتب الأمر التالي

C;\gcc> cpp filename.s أدخل

أمر مثال (كما في حالتي)

C;\gcc> cpp Alternative_letters.s

سيؤدي هذا إلى طباعة/إخراج رمز لغة التجميع بالكامل لبرنامج C الخاص بك.

استخدم "-S" كخيار.يعرض إخراج التجميع في المحطة.

أردت مؤخرًا معرفة تجميع كل وظيفة في البرنامج
هذه هي الطريقة التي فعلت ذلك.

$ 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

-save-temps

وقد ذكر هذا في https://stackoverflow.com/a/17083009/895245 ولكن اسمحوا لي أن أوضح ذلك بشكل أكبر.عندما تفعل:

gcc -save-temps -c -o main.o 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 إخراج الكائن بدلاً من دليل العمل الحالي، وبالتالي تجنب تعارضات الأسماء الأساسية المحتملة.

انتهت ميزة هذا الخيار -S هو أنه من السهل إضافته إلى أي برنامج نصي للبناء، دون التدخل كثيرًا في البناء نفسه.

شيء رائع آخر حول هذا الخيار هو إذا قمت بإضافته -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

تم الاختبار في Ubuntu 19.04 amd64 وGCC 8.3.0.

إليك حل لـ C باستخدام gcc :

gcc -S program.c && gcc program.c -o output
  1. هنا يقوم الجزء الأول بتخزين مخرجات التجميع للبرنامج بنفس اسم الملف مثل البرنامج ولكن مع تغيير بامتداد، يمكنك فتحه كأي ملف نصي عادي.

  2. يقوم الجزء الثاني هنا بتجميع برنامجك للاستخدام الفعلي وإنشاء ملف قابل للتنفيذ لبرنامجك باسم ملف محدد.

ال برنامج.ج المستخدم أعلاه هو اسم البرنامج الخاص بك و انتاج هو اسم الملف القابل للتنفيذ الذي تريد إنشاءه.

راجع للشغل، إنها أول مشاركة لي على StackOverFlow :-}

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top