frame pointer(rbp) を使わない場合は、関数の通常部分では、rsp を最初から最後まで
固定しなくては、構造化例外を処理出来なくなる。

なので、rsp が変化する事になる push, pop が使えなくなる。

(なお、人間にとっては便利でも、コンパイラにとっては、元々 push, pop は使いにくい
命令であった。)

x86、x64 アーキテクチャでは、mov reg, reg/mem のような事は出来ても、
mov mem, mem は出来ない。ところが、この、push, pop についてはそれが
出来てしまう数少ない例外。

例えば、

push qword ptr [ebp + disp1]  ;1

push qword ptr [esp + disp1]  ;2

で、ローカルの auto 変数をスタックに保存する事が出来る。ところが、

mov qwrod ptr [esp + disp1], qword ptr [esp + disp2]  ;3

とは出来ない。だから、push 命令を使うと、実はパフォーマンスが向上する可能性も
秘めてはいるかも知れない。ただし、これも、レジスタの個数が十分沢山ある
近年では、必ずしもそうとも言えないかもしれない。レジスタの個数が不足して
スタックに保存したくなった場合、

mov [esp + disp1], reg  ;4

と書けばいいわけであって、3 のように書く必要性は、近年では下がっているようだから。