내 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 noprefix
AT & 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
답변
당신이주는 경우에 GCC에게 플래그를 -fverbose-asm
, 그것은 것입니다
생성 된 어셈블리 코드에 주석을 추가로 추가하여 더 읽기 쉽게 만듭니다.
[…] 추가 된 의견은 다음과 같습니다.
- 컴파일러 버전 및 명령 행 옵션에 대한 정보
- FILENAME : LINENUMBER : CONTENT OF LINE 형식의 조립 지침과 관련된 소스 코드 행
- 다양한 어셈블리 명령어 피연산자에 해당하는 고급 표현에 대한 힌트
답변
-S (참고 : 대문자 S) 스위치를 GCC로 사용하면 확장명이 .s 인 파일에 어셈블리 코드가 생성됩니다. 예를 들어, 다음 명령은
gcc -O2 -S foo.c
생성 된 어셈블리 코드를 foo.s 파일에 그대로 둡니다.
http://www.delorie.com/djgpp/v2faq/faq8_20.html 에서 똑바로 제거 (그러나 잘못된 제거 -c
)
답변
-S
x86 기반 시스템에서 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
답변
godbolt 는 매우 유용한 도구이며 C ++ 컴파일러 만 나열하지만 -x c
코드를 C로 처리하기 위해 플래그를 사용할 수 있습니다 . 그런 다음 코드에 대한 어셈블리 목록을 나란히 Colourise
생성 하고 옵션을 사용하여 생성 할 수 있습니다 생성 된 어셈블리에 매핑 할 소스 코드를 시각적으로 나타내는 색상 막대입니다. 예를 들어 다음 코드는 :
#include <stdio.h>
void func()
{
printf( "hello world\n" ) ;
}
다음 명령 줄을 사용하십시오.
-x c -std=c99 -O3
그리고 Colourise
다음을 생성합니다 :
답변
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 년에 포기했습니다)
답변
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 : 리트 어셈블러 덤프의 끝.