GCCのWebページを図5に示します.GCCに関しては,日本語化パッチなどは必要ないので,最新情報は常にここにあります.まず,簡単なソースをコンパイルしてどのようなアセンブラソースを吐き出すかを見てみましょう.ここでは,x86用のコード生成を例に説明します.
入力するソースをリスト1に示します.Emacsなどを使用して入力してください.なお,C言語の説明が終わった頃に開発ツールの説明も簡単にしたいと思います.
〔リスト1〕test1.c
|
int f()
{
int a = 100;
int b = 200;
return a-b;
}
|
|
gcc -S test1.c
と打鍵してください.吐き出されるアセンブラのコードはリスト2のようになります.
〔リスト2〕test1.s
|
.file "tes12.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.globl f
.type f,@function
f:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
movl $100,-4(%ebp)
movl $200,-8(%ebp)
movl -4(%ebp),%eax
movl -8(%ebp),%ecx
movl %eax,%edx
subl %ecx,%edx
movl %edx,%eax
jmp .L2
.p2align 4,,7
.L2:
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size f,.Lfe1-f
.ident "GCC: (GNU) 2.95.3 20010315 (release)"
|
|
このアセンブラソースを見る限りデフォルトではint型変数はスタックされ,レジスタに入らないようです.
では,リスト3のようにソースを変更して同じようにアセンブラソースを作成してみてください(リスト4).
〔リスト3〕test2.c
|
int f()
{
register int a = 100;
register int b = 200;
return a-b;
}
|
|
〔リスト4〕test2.s
|
.file "tes23.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.globl f
.type f,@function
f:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl $100,%ecx
movl $200,%edx
movl %ecx,%ebx
subl %edx,%ebx
movl %ebx,%eax
jmp .L2
.L2:
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size f,.Lfe1-f
.ident "GCC: (GNU) 2.95.3 20010315 (release)"
|
|
リスト2とリスト4,二つのアセンブラソースを見比べるとわかりますが,意図して変数をレジスタ変数に指定した後者のソースでは,たしかにレジスタに数値が入力されています.
このように,プログラマが自らソースのコンパイル方法を指定することも最適化の一つです.この機能はグローバル変数,局所変数のどちらにも使用可能ですが,CPUに依存します.
また,リスト5,リスト6のように,どのレジスタに入れるかという指定もできます.この例ではecxレジスタに入れています.ただし,先のコードに比べてよりCPUに依存するので注意が必要です.
〔リスト5〕test3.c
|
int f()
{
register int a asm("ecx") = 100;
register int b = 200;
return a-b;
}
|
|
〔リスト6〕test3.s
|
.file "tes34.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.globl f
.type f,@function
f:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl $100,%ecx
movl $200,%edx
movl %ecx,%ebx
subl %edx,%ebx
movl %ebx,%eax
jmp .L2
.L2:
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size f,.Lfe1-f
.ident "GCC: (GNU) 2.95.3 20010315 (release)"
|
|
|