次の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 %rbp
rbp
rsp
- スタックから引数を読み取らずに、C関数(それぞれと)への引数
rsi
を自動的に含めるのはなぜですか?rdi
i
f
Fooのサイズを88バイト(11
long
秒)に増やしてみたところ、leaq
命令はになりましたimulq
。(配列アクセスを最適化するために)乗算命令を回避するために、構造体を「より丸い」サイズにするように設計することは理にかなっていますか?命令は次のleaq
ように置き換えられました。imulq $88, %rsi, %rcx