ポインタとアセンブラコードの実験
C++のポインタを使うコードがどのようにコンパイルされるかの実験です。
C++のソースコードからアセンブラコードを生成するためには、次のようなMakefileを使いました。
TARGETS = code1.s code2.s
CXXFLAGS = -O0 -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm
.PHONY: all
all: ${TARGETS}
%.s: %.cpp
${CXX} ${CXXFLAGS} -S $<
.PHONY: clean
clean:
${RM} ${TARGETS} *.o
先に比較のためにポインタを使わない、ただ変数を定義するだけのコードを書いてみます。
// code1.cpp
void foo()
{
int a = 2;
int b = 3;
int c = a + b;
}
このコードをGCCでアセンブラコードを出力するようにすると次のようになります。コメントは追加したものです。
.file "code1.cpp"
.text
.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB0:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
movl $2, -4(%rbp) # 定数2をスタックにコピー(変数a) int a=2
movl $3, -8(%rbp) # 定数3をスタックにコピー(変数b) int b=3
movl -4(%rbp), %edx # スタック(変数a)から%edxに値をコピー %edx=a:
movl -8(%rbp), %eax # スタック(変数b)から%daxに値をコピー %eax=b
addl %edx, %eax # 加算して結果を%eaxに保存 %eax=a+b
movl %eax, -12(%rbp) # 加算の結果をスタックにコピー(変数c) int c=%eax
nop
popq %rbp
.LCFI2:
ret
.LFE0:
.size _Z3foov, .-_Z3foov
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
ポインタを使ったコードを書きます。
// code2.cpp
void foo()
{
int a = 3;
int b = 4;
int* pa = &a;
int* pb = &b;
int c = *pa + *pb;
}
GCCでアセンブラコードを出力します。少し整形してコメントを足してあります。
.file "code2.cpp"
.text
.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB0:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
movl $3, -24(%rbp) # 定数3をスタックにコピー(変数a) int a=3
movl $4, -28(%rbp) # 定数4をスタックにコピー(変数b) int b=4
leaq -24(%rbp), %rax # 変数aのアドレスを%raxにコピー &a
movq %rax, -8(%rbp) # 直前でコピーしたaのアドレスをスタックに置く(変数pa)
# int* pa=%rax
leaq -28(%rbp), %rax # 変数bのアドレスを%raxにコピー &b
movq %rax, -16(%rbp) # 直前でコピーしたbのアドレスをスタックに置く(変数pb)
# int* pb=%rax
movq -8(%rbp), %rax # 変数paの値(aのアドレス)を%raxにコピー %rax=*pa
movl (%rax), %edx # %raxをアドレスとして参照先の値を%eaxにコピー %edx=*%rax
movq -16(%rbp), %rax # 変数pbの値(bのアドレス)を%raxにコピー %rax=*pb
movl (%rax), %eax # %raxをアドレスとして参照先の値を%eaxにコピー %eax=*%rax
addl %edx, %eax # %edxと%eaxを加算して%eaxに保存 %eax=*pa+*pb
movl %eax, -20(%rbp) # 加算の結果をスタックにコピー(変数c) int c=%eax
nop
popq %rbp
.LCFI2:
ret
.LFE0:
.size _Z3foov, .-_Z3foov
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits