I was observing the assembly created for the following function here.
int square(int num) {
return num;
}
This is the assembly generated for the function above:
square:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
pop rbp
ret
My question is, can I rewrite it into this and assume that it works fine?
square:
push rbp
mov rbp, rsp
mov eax, edi
pop rbp
ret
What is the need to first move edi
into [rbp-4]
and then move [rbp-4]
into eax
? Since both source and destination are registers I think we can move data in a single move instruction.
My question is about unoptimized version of code, I know if I compile it with -O1
it emits far more short and succinct code. But my question is about semantics of that extra mov
instruction.
Without optimization, the compiler generates the steps to do following a literal specification of the language. In C, the parameters to a function are essentially local variables, much as if you had declared them inside the function. So this C code:
int square(int num)
{
…
}
is, in the semantics of the C standard, much like:
int square(?)
{
int num = value that the caller passed as the first argument;
…
}
Without optimization, the compiler is following this model. When the routine starts, the compiler sets up a stack frame and stores the arguments (which are in registers) to the parameters (which are on the stack).
Then return num;
loads the parameter from the stack.
With optimization on, the compiler removes the unnecessary use of the stack.