When testing what assembler will be produced, don't use main() as the example function. Being the special function where the program starts, it tends to accumulate baggage which isn't present in any other function.
Eg.
void foo ( ) {
int a, d;
int b=12;
int c=13;
a=b+c;
d=b+c;
}
int main(void) {
foo();
return 0;
}
$ gcc -S foo.c && cat foo.s
_foo:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $12, -12(%ebp)
movl $13, -16(%ebp)
movl -16(%ebp), %eax
addl -12(%ebp), %eax
movl %eax, -4(%ebp)
movl -16(%ebp), %eax
addl -12(%ebp), %eax
movl %eax, -8(%ebp)
leave
ret
# In other words, it does exactly what the code says
$ gcc -S -O2 foo.c && cat foo.s
_foo:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
# The optimiser realises the results are never used, and the code is gone.
If foo() is declared 'static', then there isn't even that much. There is no function at all, and main() doesn't call it.
> has the opinion that you can always write better code with assembly as long
> as you stick with functions and the complexity stays low
It's certainly always "possible", and nobody is going to disagree that given enough time and experience, you can produce the equivalent translation which is better than the compiler.
But when you can write code in a high level language which achieves 95% of the performance with only 5% of the coding effort, you really need …