スタックとレジスタ
関数呼び出しにおいて,実引数はスタックまたはレジスタで渡されます。
適当なコンパイラでは関数は「まずスタックを読み込み,読み切ったら今度はレジスタから読み込む」という方式を採用しているようです(Borland,EasyIDECなど)。
これを利用して,次のようなコードが書けます。
#include <stdio.h> int main(void){ int i = 3, j = 11, k = 36; printf("%d %d %d\n"); printf("%d %d %d %d\n", j * k = i * j = 5); }
これをEasyIDECで実行すると,
「36 11 3
75 15 5 3」
と出力されます。printf関数は,「%d」を見つけて次の引数を読み込もうとしますが,スタックに何も格納されていないので,レジスタから値を読み込んでいるのです。
というかそもそもこのコード,左辺値でないものに代入しています。これは本来コンパイルエラーになるはずですが,EasyIDECはアマアマですね,プロじゃない。
どうやらEasyIDECは右から計算するようです。「j = 5」「k = i * j」「j * k」の順に計算され,EAXレジスタには75,ECXレジスタには15が残されます。printf関数はこれを読み込んでいるわけです。
恐ろしいですね。
やっぱりgccやclangを使いましょう。