次のCコードをコンパイルしました。
typedef struct {
long x, y, z;
} Foo;
long Bar(Foo *f, long i)
{
return f[i].x + f[i].y + f[i].z;
}
コマンドを使用しgcc -S -O3 test.cます。出力のBar関数は次のとおりです。
.section __TEXT,__text,regular,pure_instructions
.globl _Bar
.align 4, 0x90
_Bar:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
leaq (%rsi,%rsi,2), %rcx
movq 8(%rdi,%rcx,8), %rax
addq (%rdi,%rcx,8), %rax
addq 16(%rdi,%rcx,8), %rax
popq %rbp
ret
Leh_func_end1:
このアセンブリコードについていくつか質問があります。
- 関数の本体で使用されていない場合、
pushq %rbp「」、「」、「」movq %rsp, %rbpの目的は何ですか?popq %rbprbprsp - スタックから引数を読み取らずに、C関数(それぞれと)への引数
rsiを自動的に含めるのはなぜですか?rdiif Fooのサイズを88バイト(11
long秒)に増やしてみたところ、leaq命令はになりましたimulq。(配列アクセスを最適化するために)乗算命令を回避するために、構造体を「より丸い」サイズにするように設計することは理にかなっていますか?命令は次のleaqように置き換えられました。imulq $88, %rsi, %rcx