내 C 소스 파일에서 GCC 를 사용 하여 니모닉 버전의 기계어 코드를 덤프하여 내 코드가 컴파일되는 것을 볼 수있는 방법이 궁금합니다 . Java 로이 작업을 수행 할 수는 있지만 GCC로는 방법을 찾지 못했습니다.
어셈블리에서 C 메서드를 다시 작성하려고 시도하고 GCC가 어떻게 작동하는지 보는 것이 큰 도움이됩니다.
내 C 소스 파일에서 GCC 를 사용 하여 니모닉 버전의 기계어 코드를 덤프하여 내 코드가 컴파일되는 것을 볼 수있는 방법이 궁금합니다 . Java 로이 작업을 수행 할 수는 있지만 GCC로는 방법을 찾지 못했습니다.
어셈블리에서 C 메서드를 다시 작성하려고 시도하고 GCC가 어떻게 작동하는지 보는 것이 큰 도움이됩니다.
답변:
디버그 기호로 컴파일 objdump하면 더 읽기 쉬운 디스 어셈블리를 생성하는 데 사용할 수 있습니다 .
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel 좋다 :
-r재배치에 쇼 기호 이름 (당신이 보는 것, 그래서 puts에서 call아래 명령)-R 동적 연결 재배치 / 기호 이름 표시 (공유 라이브러리에서 유용)-C C ++ 심볼 이름 demangles-w "와이드"모드 : 기계 코드 바이트를 줄 바꿈하지 않습니다.-Mintel: .intel_syntax noprefixAT & T 대신 GAS / binutils MASM 유사 구문을 사용하십시오.-S: 디스 어셈블리가있는 소스 라인을 인터리브합니다.당신은 같은 것을 넣을 수 alias disas="objdump -drwCS -Mintel"있습니다~/.bashrc
예:
> gcc -g -c test.c
> objdump -d -M intel -S test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
int main(void)
{
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: 83 ec 10 sub esp,0x10
puts("test");
9: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
10: e8 fc ff ff ff call 11 <main+0x11>
return 0;
15: b8 00 00 00 00 mov eax,0x0
}
1a: c9 leave
1b: c3 ret
-Wa,-adhln -g to gcc. 이것은 어셈블러가 가스라고 가정하며 항상 그런 것은 아닙니다.
-Mintel.
당신이주는 경우에 GCC에게 플래그를 -fverbose-asm, 그것은 것입니다
생성 된 어셈블리 코드에 주석을 추가로 추가하여 더 읽기 쉽게 만듭니다.
[...] 추가 된 의견은 다음과 같습니다.
- 컴파일러 버전 및 명령 행 옵션에 대한 정보
- FILENAME : LINENUMBER : CONTENT OF LINE 형식의 조립 지침과 관련된 소스 코드 행
- 다양한 어셈블리 명령어 피연산자에 해당하는 고급 표현에 대한 힌트
objdump- objdump -drwCS -Mintel그래서 어떻게 같은 것을 사용할 수 verbose와를 objdump? -fverbose-asmgcc에서 와 같이 asm 코드로 주석을 작성할 수 있습니까?
-fverbose-asm추가 항목은 출력에 asm 구문으로 주석 형태로 표시되며 .o파일에 추가 항목을 넣는 지시문은 아닙니다 . 조립할 때 모두 버려집니다. 예를 들어 godbolt.org 에서 디스 어셈블리 대신 컴파일러 asm 출력 을 확인하십시오. 여기서 마우스 오버 및 해당 소스 / asm 라인의 색상 강조 표시를 통해 소스 라인과 쉽게 일치시킬 수 있습니다. GCC / clang 어셈블리 출력에서 "노이즈"를 제거하는 방법?
-S (참고 : 대문자 S) 스위치를 GCC로 사용하면 확장명이 .s 인 파일에 어셈블리 코드가 생성됩니다. 예를 들어, 다음 명령은
gcc -O2 -S foo.c생성 된 어셈블리 코드를 foo.s 파일에 그대로 둡니다.
http://www.delorie.com/djgpp/v2faq/faq8_20.html 에서 똑바로 제거 (그러나 잘못된 제거 -c)
gcc -march=native -O3 -save-temps. -c링크 등을 시도하지 않고도 객체 파일 생성을 중지 하는 데 계속 사용할 수 있습니다 .
-save-temps한 번에 정확한 코드 생성 코드를 덤프하는 반면에 컴파일러를 호출하는 다른 옵션은 -S두 번 컴파일 하고 다른 옵션을 사용하는 것을 의미합니다. 그러나 -save-temps 현재 디렉토리에 모두 덤프합니다. 코드를 검사하는 도구가 아닌 GCC의 디버그 옵션으로 의도 된 것 같습니다.
-Sx86 기반 시스템에서 GCC로 스위치를 사용하면 기본적으로 다음과 같이 -masm=att스위치 로 지정할 수있는 AT & T 구문 덤프가 생성됩니다 .
gcc -S -masm=att code.c
Intel 구문으로 덤프를 생성하려면 다음과 같이 -masm=intel스위치를 사용할 수 있습니다 .
gcc -S -masm=intel code.c
(둘 다 code.c다양한 구문, 파일로 덤프를 생성합니다 code.s)
objdump와 비슷한 효과를 내기 위해 --disassembler-options= intel/ att스위치 (예 : 구문 차이를 설명하기 위해 코드 덤프 포함)를 사용하려고합니다 .
$ objdump -d --disassembler-options=att code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483c8: 83 e4 f0 and $0xfffffff0,%esp
80483cb: ff 71 fc pushl -0x4(%ecx)
80483ce: 55 push %ebp
80483cf: 89 e5 mov %esp,%ebp
80483d1: 51 push %ecx
80483d2: 83 ec 04 sub $0x4,%esp
80483d5: c7 04 24 b0 84 04 08 movl $0x80484b0,(%esp)
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov $0x0,%eax
80483e6: 83 c4 04 add $0x4,%esp
80483e9: 59 pop %ecx
80483ea: 5d pop %ebp
80483eb: 8d 61 fc lea -0x4(%ecx),%esp
80483ee: c3 ret
80483ef: 90 nop
과
$ objdump -d --disassembler-options=intel code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
80483c8: 83 e4 f0 and esp,0xfffffff0
80483cb: ff 71 fc push DWORD PTR [ecx-0x4]
80483ce: 55 push ebp
80483cf: 89 e5 mov ebp,esp
80483d1: 51 push ecx
80483d2: 83 ec 04 sub esp,0x4
80483d5: c7 04 24 b0 84 04 08 mov DWORD PTR [esp],0x80484b0
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov eax,0x0
80483e6: 83 c4 04 add esp,0x4
80483e9: 59 pop ecx
80483ea: 5d pop ebp
80483eb: 8d 61 fc lea esp,[ecx-0x4]
80483ee: c3 ret
80483ef: 90 nop
gcc -S -masm=intel test.c나를 위해 정확히 일을했다, 내가 인텔과 같은 AT & T 구문의 일부 잡종을 가지고 : mov %rax, QWORD PTR -24[%rbp]대신에, : movq -24(%rbp), %rax.
.oASM 파일과 ASM 파일 의 병렬 출력을 수행 할 때도 작동합니다.-Wa,-ahls -o yourfile.o yourfile.cpp>yourfile.asm
-M옵션을 사용할 수 있습니다 --disassembler-options. 예 와 같지만 훨씬 짧습니다.objdump -d -M intel a.out | less -N
godbolt 는 매우 유용한 도구이며 C ++ 컴파일러 만 나열하지만 -x c코드를 C로 처리하기 위해 플래그를 사용할 수 있습니다 . 그런 다음 코드에 대한 어셈블리 목록을 나란히 Colourise생성 하고 옵션을 사용하여 생성 할 수 있습니다 생성 된 어셈블리에 매핑 할 소스 코드를 시각적으로 나타내는 색상 막대입니다. 예를 들어 다음 코드는 :
#include <stdio.h>
void func()
{
printf( "hello world\n" ) ;
}
다음 명령 줄을 사용하십시오.
-x c -std=c99 -O3
그리고 Colourise다음을 생성합니다 :

-masm=intel나머지는 어떻습니까?
-x c
gcc -S -fverbose-asm -O source.c그런 다음 생성 된 source.s어셈블러 파일 을 살펴 보셨습니까 ?
생성 된 어셈블러 코드가 들어갑니다 source.s( -o 어셈블러 파일 이름으로 대체 할 수 있음 ). 이 -fverbose-asm옵션은 컴파일러에게 생성 된 어셈블러 코드를 "설명"하는 어셈블러 주석을 생성하도록 요청합니다. 이 -O옵션은 컴파일러에게 비트를 최적화하도록 요청합니다 ( -O2또는로 더 최적화 할 수 있음 -O3).
무엇을하고 있는지 이해하고 싶다면 신중하게 gcc통과 -fdump-tree-all해야합니다. 수백 개의 덤프 파일을 얻게됩니다.
BTW, GCC는 플러그인 또는 MELT (GCC를 확장하기위한 고급 도메인 특정 언어로 확장 가능합니다 .2017 년에 포기했습니다)
source.s많은 사람들이 콘솔에서 인쇄물을 기대하기 때문에 출력이에 있다고 언급 할 수도 있습니다 .
-S -o-표준 출력으로 덤프합니다. -masm=intelNASM / YASM 구문을 사용하려는 경우에 유용합니다. ( qword ptr [mem]단지가 아니라을 사용 qword하므로 NASM / YASM보다 Intel / MASM과 비슷합니다). gcc.godbolt.org 는 덤프를 정리하는 작업을 훌륭하게 수행합니다. 선택적으로 주석 전용 행, 사용하지 않는 레이블 및 어셈블러 지시문을 제거합니다.
-Og보다 좋습니다 -O1. "디버깅 최적화"를 의미하며 소스가 말하는 모든 것을 수행하는 까다 롭고 따르기 어려운 최적화없이 asm을 만듭니다. gcc4.8부터 사용할 수 있지만 clang 3.7에는 아직 없습니다. IDK가 반대하거나 결정한 경우.
objdump와 같이 gdb를 사용할 수 있습니다.
이 발췌문은 http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64 에서 가져 왔습니다 .
다음은 Intel x86의 혼합 소스 + 어셈블리를 보여주는 예입니다.
(gdb) disas / m main
함수 main을위한 어셈블러 코드 덤프 :
5 {
0x08048330 : 푸시 % ebp
0x08048331 : mov % esp, % ebp
0x08048333 : 하위 $ 0x8, % esp
0x08048336 : 및 $ 0xfffffff0, % esp
0x08048339 : 하위 $ 0x10, % esp
6 printf ( "안녕하세요. \ n");
0x0804833c : movl $ 0x8048440, (% esp)
0x08048343 : 전화 0x8048284
7은 0을 반환합니다.
8}
0x08048348 : mov $ 0x0, % eax
0x0804834d : 휴가
0x0804834e : 리트
어셈블러 덤프의 끝.
set disassembly-flavor intelcommand를 사용하십시오 .
나는 gcc에게 기회를주지 않았지만 g ++의 경우. 아래 명령은 저에게 효과적입니다. 디버그 빌드의 경우 -g 및 -Wa, -adhln은 소스 코드로 나열하기 위해 어셈블러로 전달됩니다.
g ++ -g-와아, 아들 src.cpp
gcc 또는 g ++에서 옵션으로 -Wa, -adhln 을 사용 하여 stdout에 리스팅 출력을 생성하십시오.
-Wa, ...는 어셈블러 부분의 명령 행 옵션입니다 (C / ++ 컴파일 후 gcc / g ++에서 실행). 그것은 호출 로 (Windows의 as.exe) 내부. 보다
> 도움말
gcc 내부의 어셈블러 도구에 대한 추가 도움말을 보려면 명령 줄로