[gcc]前置インクリメントと後置インクリメントで生成されるアセンブラコードの違い

今回のお題:
以下の文脈で、前置インクリメントと後置インクリメントを行った。
生成されるアセンブラコードは、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をコールしてました。

関連記事

コメントを残す

メールアドレスが公開されることはありません。