I don't understand why the following lines are using
movl to push data below the stack pointer are produced by GCC.
movl -4(%ebp), %eax # -4(%ebp) <- local variable 1
movl 8(%ebp), %edx # 8(%ebp) <- first parameter
movl %edx, 8(%esp) # ??? WHY NOT: pushl %edx
movl %eax, 4(%esp) # ??? WHY NOT: pushl %eax
movl -8(%ebp), %eax # ??? WHY NOT: pushl -8(%ebp)
movl %eax, (%esp)
movl %eax, f
I guess this code tries to push 3 parameters for the function call. But why isn't it using
pushl. What is the usage of this code and how does this work?
Best How To :
Hans Passant answered correctly. The push/pop opcodes can be broken down into two micro-ops which do a memory move and an increment/decrement of the stack pointer. If the stack pointer - or any pointer - is updated and then immediately used in the next opcode, an execution stall generally occurs. By accessing the individual memory locations through the stack pointer - as in your example - there would be no stall and the operations could be paired allowing them to be executed simultaneously.
Any superscalar CPU type will attempt to execute multiple opcodes in a single cycle if their results/sources have nothing to do with one another. The compiler is doing something for you to speed up execution that would be fairly laborious to do by hand. The opcodes may occupy more space than pushes, but they will execute roughly twice as fast - all other things being the same.