Consider, say, shadow stacks- local variables might end up living on a totally separate "stack" from the one "call" pushes onto and "ret" pops from, and one which the ISA has no idea about.
Consider, say, shadow stacks- local variables might end up living on a totally separate "stack" from the one "call" pushes onto and "ret" pops from, and one which the ISA has no idea about.
PUSH/POP are more obviously "hey store your locals on the stack, kids", but on, say, x64, how often do you actually see a push instead of bp/sp-relative addressing? Most compilers seem to be much happier representing each stack frame as "a bunch of slots, some for things where the address is taken so it needs to be in memory, and others where I spill things into as needed".
On ARMv7 (i don't know enough about v8 / AARCH64), "push"/"pop" are just stores/loads with postdecrement / postincrement.
Is this lawyer-y? Sure. But I think it's still correct, and this being HN...
It's much more optimal to use a series of push/pops for smaller operations like saving registers before a call than to manually adjust and store onto the stack.
While technically this is still incrementing/decrementing a register and storing, the amount of isa/hardware support for such things clearly demonstrates that the x86 isa and modern x86 hardware gives special treatment to the stack.