Neccessity of push and pop operands on CPUs
assembly, att, cpu, cpu-architecture, stack
Solution
But then, there's no reason for a `CALL` instruction, either. After all, you can simulate a call with:
sub esp,4
mov [esp-4], offset return_address
jmp myproc
And there's no need for a `RET` instruction, either, because you can simulate it with:
mov eax,[esp]
add esp,4
jmp [eax]
If you look hard enough, you'll find lots of instructions that can be simulated by combining other instructions. What's the point?
The answer to these types of questions is rooted in the long history of the x86 processor family, and in processors that came before it. The designers studied how programmers use processors and created an instruction set that was efficient in terms of execution speed and memory use.
In the late '70s, 64 kilobytes was a lot of RAM, and RAM was much slower. Every instruction byte was precious, and there was a huge amount of overhead just fetching an instruction from memory. It was not uncommon for instruction fetch to take longer than execution. So there was a huge performance gain to be had by encoding things in as few instruction bytes as possible.
RAM is still incredibly slow when compared to CPU clock speeds, so there's still a gain to be had by encoding in as few instruction bytes as possible. It's true that the large CPU caches we have help a great deal, as does branch prediction and prefetch logic, but every byte transferred from RAM to the CPU cache is still expensive. It pays to be frugal with instruction encodings.
About calling procedures:
The standard way of calling procedures in assembly language is to push the parameters and then `call` the procedure. For example, this passes two dword values:
push eax
push ebx
call proc ; pushes the return address and jumps to proc
...
proc:
; at this point, [esp] contains the return address
The `ret` instruction pops the return address into the instruction pointer.
Somebody has to clean up the stack, of course. The caller can clean up the stack by incrementing the stack pointer. Or the called procedure can clean up the stack by using `ret 8`, which will pop the return address and increment the stack pointer.
See http://www.delorie.com/djgpp/doc/ug/asm/calling.html for more info on calling conventions.
Problem
Why do we have commands like push and pop? From what I understand `pop` and `push` are basically the same as doing a (`mov` then `add`) and (`sub` then `mov`) on `esp` respectively. For example wouldn't: ``` pushl %eax ``` be equivalent to: ``` subl $4, %esp movl %eax, (%esp-4) ``` please correct me if stack access is not `(%esp-4)`, I'm still learning assembly The only true benefit I can see is if doing both operation simultaneously offers some advantage; however I don't see how it could.