Convención de llamada x86: ¿los argumentos pasados por la pila deben ser de solo lectura?
Parece que los compiladores de vanguardia tratan los argumentos pasados por stack como de solo lectura. Tenga en cuenta que en la convención de llamadas x86, la persona que llama empuja los argumentos a la pila y la persona que llama utiliza los argumentos en la pila. Por ejemplo, el siguiente código C:
extern int goo(int *x);
int foo(int x, int y) {
goo(&x);
return x;
}
es compilado porclang -O3 -c g.c -S -m32
en OS X 10.10 en:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 10
.globl _foo
.align 4, 0x90
_foo: ## @foo
## BB#0:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
leal -4(%ebp), %eax
movl %eax, (%esp)
calll _goo
movl -4(%ebp), %eax
addl $8, %esp
popl %ebp
retl
.subsections_via_symbols
Aquí el parámetrox
(8(%ebp)
) se carga primero en%eax
; y luego almacenado en-4(%ebp)
; y la dirección-4(%ebp)
se almacena en%eax
; y%eax
se pasa a la funcióngoo
.
Me pregunto por qué Clang genera código que copia el valor almacenado en8(%ebp)
a-4(%ebp)
, en lugar de simplemente pasar la dirección8(%ebp)
a la funcióngoo
. Ahorraría operaciones de memoria y daría como resultado un mejor rendimiento. También observé un comportamiento similar en GCC (bajo OS X). Para ser más específico, me pregunto por qué los compiladores no generan:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 10
.globl _foo
.align 4, 0x90
_foo: ## @foo
## BB#0:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
leal 8(%ebp), %eax
movl %eax, (%esp)
calll _goo
movl 8(%ebp), %eax
addl $8, %esp
popl %ebp
retl
.subsections_via_symbols
Busqué documentos si la convención de llamadas x86 exige que los argumentos pasados sean de solo lectura, pero no pude encontrar nada sobre el tema. ¿Alguien tiene alguna idea sobre este tema?