今回考えるのは、PUSH・POPにおいてESPの変化と値を取り出すタイミングがどの順番で行われているかということだ。
実験に使用するコードはこれ。
.code32 .globl push_test, pop_test .text push_test: subl $4, %esp ## here! movl $0x12345678, (%esp) ## here! popl %eax ret pop_test: pushl $0x12345678 movl (%esp), %eax ## here! addl $4, %esp ## here! ret
C言語からは次のように呼び出す。
printというのは自作のprintf関数だ。
unsigned int push_test(); unsigned int pop_test(); int main(int argc, char **argv, char **envp){ print("push_test() = %x, pop_test() = %x\n", push_test(), pop_test()); return 0; }
実行結果は次のようになった。
push_test() = 12345678, pop_test() = 12345678
この結果から、PUSH・POPを行う直前のESPは最後に操作した値を指しているということがわかる。
最後にPUSH・POPを模倣したコードを載せておく。
PUSH
subl $4, %esp
movl 値, (%esp)
POP
movl (%esp), %eax
addl $4, %esp