2017-11-21 15 views
-1

私は、cプログラムから生成されたアセンブリコードの意味を見出そうとしています。ここにはC言語のプログラムがあります:コンパイラは無駄なアセンブリコードを生成できますか?

int* a = &argc; 
int b = 8; 
a = &b; 

ここでは、説明付きで生成されたアセンブリコードを示します。メインの

プロローグ:

leal 4(%esp), %ecx 
andl $-16, %esp 
pushl -4(%ecx) 
pushl %ebp 
movl %esp, %ebp 
pushl %ecx 
subl $36, %esp 

ロード%eaxに中のargcのアドレス:

movl %ecx, %eax 

一部私は取得しない:私は理解していない1つの部分があります

movl 4(%eax), %edx 
movl %edx, -28(%ebp) 

スタックスマッシングプロテクターコード(セットアップ):

aとbでの
movl %gs:20, %ecx 
movl %ecx, -12(%ebp) 
xorl %ecx, %ecx 

負荷値(main.cの中で参照)

leal -20(%ebp), %eax 
movl %eax, -16(%ebp) 

スタックスマッシングプロテクタコード:

movl %eax, -16(%ebp) 
movl $8, -20(%ebp) 

は(A = & B)の値を変更します(スタックを確認okです):

movl $0, %eax 
movl -12(%ebp), %edx 
xorl %gs:20, %edx 
je .L7 
call __stack_chk_fail 

スタックがOKの場合:

.L7: 
    addl $36, %esp 
    popl %ecx 
    popl %ebp 
    leal -4(%ecx), %esp 
    ret 
は、だから私は-28(%のEBP)の値を変更しているuinderstandていない部分は、アドレスが使用されることはありません。誰かがなぜこの部分が生成されているのか分かっていますか?

+6

最適化せずにコンパイルすると(デフォルト)、コンパイラの出力には、必要ない場合でもすべてのロード/ストアがメモリに格納されます。あなたのコードを取り出し、 'main'以外の関数に入れて、' -O3'の最適化でコンパイルしてください。 –

+0

main()を使わないでください。テスト中のコードを他の関数名にしてください。main()の質問は何度も尋ねられています。 –

+2

最適化フラグを指定しないことで脳を消すようにコンパイラに指示しましたが、今は奇妙なコードが生成されるのでしょうか? – fuz

答えて

6

コンパイラの機能を確認するには良い方法です。その後で同じことを行う

$ objdump -S main.o 

main.o:  file format elf64-x86-64 


Disassembly of section .text: 

0000000000000000 <main>: 
int main(int argc, char **argv) 
{ 
    0: 55      push %rbp 
    1: 48 89 e5    mov %rsp,%rbp 
    4: 89 7d ec    mov %edi,-0x14(%rbp) 
    7: 48 89 75 e0    mov %rsi,-0x20(%rbp) 
    int* a = &argc; 
    b: 48 8d 45 ec    lea -0x14(%rbp),%rax 
    f: 48 89 45 f8    mov %rax,-0x8(%rbp) 
    int b = 8; 
    13: c7 45 f4 08 00 00 00 movl $0x8,-0xc(%rbp) 
    a = &b; 
    1a: 48 8d 45 f4    lea -0xc(%rbp),%rax 
    1e: 48 89 45 f8    mov %rax,-0x8(%rbp) 
    22: b8 00 00 00 00   mov $0x0,%eax 
} 
    27: 5d      pop %rbp 
    28: c3      retq 

:アセンブリを見る

$ gcc -c -g main.c 

:オブジェクトファイルにデバッグ情報と

int main(int argc, char **argv) 
{ 
    int* a = &argc; 
    int b = 8; 
    a = &b; 
} 

コンパイル:私はあなたのmain.cというファイルがあるとし完全最適化:

$ gcc -c -g -O3 main.c 

アセンブリをもう一度見てください:

$ objdump -S main.o 

main.o:  file format elf64-x86-64 


Disassembly of section .text.startup: 

0000000000000000 <main>: 
int main(int argc, char **argv) 
{ 
    int* a = &argc; 
    int b = 8; 
    a = &b; 
} 
    0: 31 c0     xor %eax,%eax 
    2: c3      retq 

答えははいです。コンパイラは必要のない命令を生成できます。そのため、最適化を有効にしています。それらがオフになると、コンパイラは全く考えずに非常に汎用的な方法でその仕事をします。たとえば、使用されていない変数の領域を予約します。

+0

ありがとうございます。私が驚いたことにわかったのは、アセンブリの部分がCのソースコードのどの部分にも対応していなかったことです。しかし、プログラムは何もしないので、アセンブリのすべての行は役に立たないと考えられるべきです。 –

+1

コンパイラが何をしているのかを見るために、コンパイルとディスアセンブルを行うC関数を作る技術があります。低い最適化レベルコンパイラはスタック/メモリにすべてを保存し、そこにフォームを取得します。デッドコードがあると、読んでいないものが書き込まれる可能性がありますが、それはプログラムがその可能性があるためです。デッドコードではない、または興味のないものに最適化されたテスト関数を書くことは、ある程度の練習を必要とします。 –

+1

@DJ_Joe:https://stackoverflow.com/questions/38552116/how-to-remove-noise-from-gcc-clang-assembly-outputを参照してください。特にMatt GodboltのCppCon2017トーク:「What Has My Compiler最近私のためにやりましたか?コンパイラの蓋を解く ""(https://youtu.be/bSkpMdDe4g4)、これはまさに@ old_timeが話していたものです。 –

関連する問題