見出し画像

記事『だからCってやつは *p++』に乱入してみるよ!

はお。

ちょっと面白そうだったので乱入してみようと思いますw
AyumiKatayamaさんの以下の記事……

*p++ に翻弄されているご様子。読んでいて混乱しますし、後置++ の優先順位が高いとか マジか って思ったので調査です調査!

前置きはなしで、じゃんっ!

挙動の確認できるテストプログラムのアセンブラを紐解いていきましょう。C側のソースでは 9行目ですね。アセンブラでは 19行目~ 24行目になりまする。

とその前にちゃんと見ていかないとね。冒頭の変数初期化部分。Cでは、

int v = 1;
int c = 0;
int* p = &v;

となり、アセンブラでは、

mov     DWORD PTR _v$[ebp], 1
mov     DWORD PTR _c$[ebp], 0
lea     eax, DWORD PTR _v$[ebp]
mov     DWORD PTR _p$[ebp], eax

となっています。これは変数 v のアドレス部に 1を代入、変数 c のアドレス部に 0を代入、ポインタ p は、eax レジスタに v のアドレスを入れて、変数 p(v) のアドレス部に eax レジスタの内容を代入していると分かれば OKです。

これを踏まえたうえで c = *p++ を見ていきましょう。
じゃん。

mov     ecx, DWORD PTR _p$[ebp]
mov     edx, DWORD PTR [ecx]
mov     DWORD PTR _c$[ebp], edx
mov     eax, DWORD PTR _p$[ebp]
add     eax, 4
mov     DWORD PTR _p$[ebp], eax

うわぁ、なんかごちゃごちゃするので必要なものだけにしてみます。

mov     ecx     , _p$[ebp]
mov     edx     , [ecx]
mov     _c$[ebp], edx
mov     eax     , _p$[ebp]
add     eax     , 4
mov     _p$[ebp], eax

なんとなく見やすくなったかな?

この中で注目すべきは add の部分、これが ++ に相当するところですね。その前の行で eax レジスタに p(v) のアドレス値を入れています。そして addeax レジスタに 4 加算するとアドレスが 4 進むわけですね。つまり p++

始めの 3行では c = *p が行われています。ecx レジスタに p(v) のアドレス値を入れ、edx レジスタには ecx(アドレス)の実体を入れています。そして cedx を入れて c = *p の完成でっす。

処理的には c = *p が先に行われ、次に p++ が処理されていますね…… 優先順位とかもうよくわかりません(==;

とりあえず、後置++ の挙動の確認が取れたのでよしとしましょう!(ぉ

悉く書を信ずれば則ち書無きに如かず