今回のお題:
以下の文脈で、前置インクリメントと後置インクリメントを行った。
生成されるアセンブラコードは、iとjでどう変わるのか?
#include <stdio.h> int main() { int i = 0; int j = 0; for ( i = 0, j = 0; i < 5 ; ) { printf( "ptn2 i = %d, j = %d\n", ++i, j++ ); } return 0; } |
使用したコンパイルオプションは以下の通りです。
gcc -Wall -S -o incTest incTest.c |
生成されたコード(incTest.s)は以下の通りになりました。
長くなるので必要部のみ抜粋します。(頭の数字は行番号です)
38 movl $0, 28(%esp) 39 movl $0, 24(%esp) 40 jmp L4 41 L5: 42 movl 24(%esp), %eax 43 addl $1, 24(%esp) 44 addl $1, 28(%esp) 45 movl %eax, 8(%esp) 46 movl 28(%esp), %eax 47 movl %eax, 4(%esp) 48 movl $LC1, (%esp) 49 call _printf 50 L4: 51 cmpl $4, 28(%esp) 52 jle L5 |
このコードを解読してます。
解読結果はコメントの形で追加しました。
38 movl $0, 28(%esp) ; i = 0 39 movl $0, 24(%esp) ; j = 0 40 jmp L4 41 L5: 42 movl 24(%esp), %eax ; $eax = j 43 addl $1, 24(%esp) ; j = j+1 44 addl $1, 28(%esp) ; i = i+1 45 movl %eax, 8(%esp) ; esp[8] = eax 46 movl 28(%esp), %eax ; eax = i 47 movl %eax, 4(%esp) ; esp[4] = eax 48 movl $LC1, (%esp) ; esp[0] = strPtr 49 call _printf ; printfを呼び出し 50 L4: 51 cmpl $4, 28(%esp) if ( i <= 4 ) { goto L5; } 52 jle L5 53 movl $0, %eax 54 leave |
見てみると、上記コードの場合はprintfの呼び出し前にi,jとも加算してしまっているようです。
加算前の値をeaxレジスタに退避したうえで,その値をスタックに乗せてprintfをコールしてました。
関連記事
コメントを残す