linux x86 calling-convention

linux - C convenciones de llamadas y argumentos pasados



x86 calling-convention (4)

Aunque la persona que llama (en algunas convenciones de llamadas) es la que limpia los argumentos, lo único que hace es desasignar el espacio previamente asignado en la pila para mantener los valores del argumento. El destinatario es libre de modificar los valores durante la ejecución de la función, porque la persona que llama no va a ver sus valores más tarde.

En el ejemplo que publicó, GCC ha emitido la instrucción popl %eax para desasignar el espacio tomado por el parámetro en la pila. Todo lo que necesita hacer es agregar 4 a% esp (la pila en x86 crece hacia abajo en la memoria) y ejecutar la instrucción popl %eax es la manera más rápida y corta de hacerlo. Si el compilador necesitaba desasignar 20 valores, probablemente modificaría% esp directamente en lugar de emitir 20 instrucciones popl .

Probablemente encontrará que el nuevo valor de% eax no se usa en el siguiente código.

Al realizar una llamada de función en Linux (u OS X para el caso), ¿puede el destinatario modificar los valores de los argumentos en la pila? Estaba bajo el supuesto de que, dado que la persona que llama es la que los limpia, deben contener los mismos valores después de la llamada a la función. Sin embargo, descubrí que GCC con -O2 estaba modificando los parámetros que se le habían pasado en la pila. También busqué documentación que incluye las convenciones de llamadas System V i386, pero no pude encontrar una respuesta definitiva a esto.

Aquí hay un código de muestra que estaba depurando.

pushl %eax # %eax = 0x28 call _print_any popl %eax # %eax is now 0x0a

Supongo que GCC modificando ese parámetro en la pila está bien, pero quiero saber dónde se especifica que puede hacerlo.


En la norma C, el destinatario puede modificar los valores de sus argumentos todo lo que quiera, pero la persona que llama nunca verá los cambios.

Lo que puede ser confuso es que si uno pasa un POINTER a un valor, entonces el destinatario puede cambiar ese valor desreferenciando el puntero, pero si el destinatario realmente cambia el puntero, la persona que llama no verá ese cambio.

Una pequeña queja: el estándar C no requiere que la implementación tenga TAMBIÉN una pila.


Sí, el destinatario puede modificar los argumentos en la pila. En lo que respecta al destinatario, son lo mismo que las variables locales. La persona que llama los limpia, pero ignora el valor.

Si está hablando C o C ++ POD, la limpieza simplemente está modificando el puntero de la pila.

Si está hablando de C ++ con un destructor, la persona que llama es responsable de invocar el destructor, pero los destructores para las clases genéricas deben escribirse para limpiar cualquier valor.


Si pasa por valor:

call do_it(to_it);

El argumento se copia (probablemente al principio de la pila, pero tal vez no depende de tu compilador), el programa de celdas puede interferir con esta copia todo lo que quiera, pero la variable en el programa no se cambiará.

Si pasa por referencia:

call do_it(&to_it);

Luego se pasa la dirección de la variable. Cualquier cambio que realice la variable llamada será a la variable original en el programa de llamada.