All the registers?
[snip (function f)]
.type f,@function
f:
pushl %ebp
movl %esp,%ebp
movl a,%eax
movl %ebp,%esp
popl %ebp
ret
[end snip]
[snip (part of main())]
movl $4,e
call f
movl %eax,%ecx
[end snip]
Which registers are getting pushed on the stack? EBP, EIP, CS. That's
it. Let's see what happens with:
gcc -O2 -fomit-frame-pointer -ansi -pedantic -o aaa aaa.c
[snip (function f)]
.type f,@function
f:
movl a,%eax
ret
[end snip]
[snip (part of main())]
call f
[end snip]
Now only CS and EIP (implictly through call/ret).
And now with:
gcc -O2 -fomit-frame-pointer -finline-functions -ansi -pedantic -o aaa
aaa.c
[snip (part of main())]
movl $4,e
movl a,%eax
addl $9,%eax
[end snip]
And an excerpt from K&R 2nd ed. (p200):
"The precedence and associativity of operators is fully specified, but the
order of evaluation of expressions is, with certain exceptions, undefined,
even if the subexpressions involve side-effects. That is, unless the
definition of an operator guarantees that its operands are evaluated in a
particular order, the implementation is free to evaluate operands in any
order, or even to interleave their evaluation."
Lessons:
Compiler output tells us nothing conclusive about a programming language.
Compilers can optimize many functions by inlining them without changing
their semantics.
Don't rely on a certain calling order for functions with side-effects.
It's the Wrong Thing To Do.
Don't rely on expression evaluation order for anything other than &&, ||,
and (comma).
- Robert Minichino
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu