Pregunta

Cuando se hace una llamada a la función en Linux (o OS X para el caso), el destinatario puede modificar los valores de los argumentos en la pila? Estaba bajo el supuesto de que, dado que la persona que llama es el que los limpia, que deben contener los mismos valores después de la llamada de función. Sin embargo, me encontré con que GCC -O2 estaba modificando los parámetros que se han pasado a ella en la pila. También he buscado la documentación, incluyendo las convenciones de llamada i386 System V, pero fue incapaz de encontrar un definitiva respuesta a esto.

A continuación, algunos ejemplos de código que estaba depuración.

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

Me gustaría asumir que GCC modificando ese parámetro en la pila está muy bien, pero quiero saber donde se especifica que puede hacerlo.

¿Fue útil?

Solución

A pesar de que la persona que llama (en algunas convenciones de llamada) es el que limpia los argumentos, todo lo que está haciendo en realidad es desasignar el espacio previamente asignado en la pila para mantener los valores de los argumentos. El destinatario de la llamada es libre de modificar los valores durante la ejecución de la función, debido a que la persona que llama no se va a ver en sus valores más tarde.

En el ejemplo informados, GCC ha emitido la instrucción popl %eax desasignar el espacio ocupado por el parámetro en la pila. Todo lo que realmente necesita hacer es agregar a 4% esp (la pila crece en x86 abajo en la memoria), y ejecutar la instrucción popl %eax es el camino más corto y rápido para hacer esto. Si el compilador necesita para desasignar 20 valores, es probable que modificar% esp directamente en lugar de emitir instrucciones popl 20.

Es probable que encuentre que el nuevo valor de% eax no se utiliza en el siguiente código.

Otros consejos

Sí, el destinatario de la llamada puede modificar los argumentos en la pila. En lo que se refiere al destinatario de la llamada, que son las mismas que las variables locales. El llamador limpiarlos, pero ignora el valor.

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

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

En C estándar, el destinatario de la llamada puede modificar los valores de sus argumentos todos que quiere, pero la persona que llama no volverá a ver los cambios.

Lo que puede ser confuso es que si uno pasa un puntero a un valor, entonces el destinatario de la llamada puede cambiar ese valor por la eliminación de referencias del puntero, pero si el destinatario de la llamada en realidad cambia el puntero en sí la persona que llama no podrá ver ese cambio.

Una pequeña nit: el estándar C no requiere que la aplicación incluso tener una pila

.

Si pasa por valor:

call do_it(to_it);

se copia el argumento (probablemente a principios de la pila, pero quizás no en función de su compilador) el programa unicelular puede no cambiará meterse con esta copia tanto como se quiera, pero la variable en el programa clling.

Si pasa por referencia:

call do_it(&to_it);

A continuación, se pasa el Dirección de la variable. Cualquier cambio las llamadas marcas variables estarán a la variable original en el programa de llamada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top