문제

이것을 어떻게합니까?

무언가가 어떻게 컴파일되는지 분석하려면 어떻게 방출 된 어셈블리 코드를 얻을 수 있습니까?

도움이 되었습니까?

해결책

사용 -S GCC 옵션 (또는 G ++).

gcc -S helloworld.c

이렇게하면 Helloworld.c를 통해 전처리 (CPP)를 실행하고 초기 편집을 수행 한 다음 어셈블러가 실행되기 전에 중지됩니다.

기본적으로 파일을 출력합니다 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를 사용하여 얻을 수있는 세부 사항 수준에 대한 표시를 제공합니다.

다른 팁

이렇게하면 C 코드 + 줄 번호가 연결되어 ASM 코드가 생성되어 어떤 줄이 어떤 코드를 생성하는지 더 쉽게 알 수 있습니다.

# 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의 전체 15 번째 페이지).

다음 명령 줄은 Christian Garbin의 블로그

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

나는 win-xp의 dos 창에서 G ++를 실행했다.

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와 함께

gcc -S main.c

또한 참조하십시오 이것

보고 싶은 것이 출력의 링크에 의존하는 경우, 출력 개체 파일/실행 파일의 OBJDUMP는 위에서 언급 한 GCC -S 외에 유용 할 수 있습니다. 다음은 Loren Merritt의 매우 유용한 스크립트입니다. 기본 OBJDUMP SYNTAX를보다 읽기 쉬운 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 GCC 옵션. 또한 최적화 옵션을 추가할지 여부에 따라 결과가 다를 수 있다고 덧붙이고 싶습니다.-O0 없음, -O2 Agressive 최적화를 위해).

특히 RISC 아키텍처에서 컴파일러는 종종 최적화를 수행 할 때 인식을 넘어서 코드를 거의 변환합니다. 결과를 보는 것은 인상적이고 매력적입니다!

앞에서 언급했듯이 -s 플래그를보십시오.

또한 '-fdump-tree'깃발, 특히 '-fdump-tree-all'제품군을 보면 GCC의 중간 형태를 볼 수 있습니다. 이것들은 종종 어셈블러보다 더 읽기 쉬울 수 있으며 (적어도 나에게) 최적화가 어떻게 수행되는지 볼 수 있습니다.

-s 옵션을 사용합니다.

gcc -S program.c

LLVM 어셈블리를 찾고 있다면 :

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

질문이 2008 년 이었기 때문에 답들 사이에 이러한 가능성이 보이지 않지만 2018 년에는 Matt Goldbolt의 온라인 웹 사이트를 사용할 수 있습니다. https://godbolt.org

당신은 또한 현지에서 클론을하고 그의 프로젝트를 실행할 수 있습니다. https://github.com/mattgodbolt/compiler-explorer

에서: http://www.delorie.com/djgpp/v2faq/faq8_20.html

gcc -c -g -wa, -a, -ad [기타 GCC 옵션] foo.c> foo.lst

Phirephly의 대답을 대안하거나 모든 사람이 말했듯이 -S를 사용합니다.

Output of these commnads

다음은 Windows에서 C 프로그램의 어셈블리 코드를보고 인쇄하는 단계입니다.

콘솔 / 터미널 / 명령 프롬프트 :

  1. CodeBlocks와 같은 C 코드 편집기에 C 프로그램을 작성하고 Extention .C로 저장하십시오.

  2. 컴파일하고 실행하십시오.

  3. 성공적으로 실행되면 GCC 컴파일러를 설치 한 폴더로 이동하여

    '.c'파일의 '.s'파일을 얻으려면 명령을 따릅니다.

    C : gcc> gcc-s C 파일의 완전한 경로 Enter

    예제 명령 (내 경우와 같이)

    C : gcc> gcc -sd : aa_c_certified anllate_letters.c

    이것은 원본 '.c'파일의 '.s'파일을 출력합니다.

4. 그런 다음 다음 명령을 입력하십시오

c; gcc> cpp filename.s는 입력합니다

예제 명령 (내 경우와 같이)

C; GCC> CPP Alternate_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

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

우분투 19.04 AMD64, GCC 8.3.0에서 테스트.

다음은 GCC를 사용하는 C를위한 솔루션입니다.

gcc -S program.c && gcc program.c -o output
  1. 여기서 첫 번째 부분은 프로그램의 어셈블리 출력을 프로그램과 동일한 파일 이름으로 저장하지만 변경 사항이 있습니다. .에스 확장자, 일반 텍스트 파일로 열 수 있습니다.

  2. 두 번째 부분은 실제 사용을 위해 프로그램을 컴파일하고 지정된 파일 이름으로 프로그램에 대한 실행 파일을 생성합니다.

그만큼 program.c 위에 사용 된 프로그램의 이름은 다음과 같습니다 산출 생성하려는 실행 파일의 이름입니다.

btw 그것은 stackoverflow에 대한 나의 첫 번째 게시물입니다 :-}

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top