Pregunta

Yo uso en línea de montaje de forma masiva en un proyecto donde tengo que llamar a las funciones con un número indeterminado de argumentos en tiempo de compilación y mientras yo me las arreglo para conseguir que funcione, a veces, en Linux (en las ventanas no recuerdo tener ese problema) cosas extrañas como pasar esto:

Si tengo algo así como

for(int i = 1; i >= 0; i--)
   asm("push %0"::"m"(someArray[i]));

Funciona.

Si tengo

for(int i = this->someVar; i >= 0; i--)
   asm("push %0"::"m"(someArray[i]));

y garantizo con mi vida que somevar está sosteniendo el valor 1 se lanza fallo de segmentación.

Además, si tengo

int x = 1;
for(int i = x; i >= 0; i--)
   asm("push %0"::"m"(someArray[i]));

funciona, pero

int x = this->someVar;
for(int i = x; i >= 0; i--)
    asm("push %0"::"m"(someArray[i]));

no.

Además, y también curiosamente, lo que puedo decir que, si bien en algunas funciones no tengo problemas para hacerlo en los demás lo que tengo, todo en el mismo objeto.

Si alguien me puede apuntar a una cierta información que puede aclarar cuál es el problema existe, apreciaría.

Tenga en cuenta que realmente tengo que empujar los argumentos en un bucle for evitando así que no es una opción.

También he intentado usar la palabra ensamblado en línea "volátil", pero nada ha cambiado.

¿Fue útil?

Solución

No puedo entender cuál es el problema, sino tratar de escribir código utilizando el código asm clara mismo que

asm{
   loop1:
     mov ax, this->var
     ...
     dec ax
     cmp ax, 0
     je exit
     jmp loop1
}

...

Salida:

Además, trate de hacer que el valor "var", como se estática puede ayudar también.

Otros consejos

Examinar el desmontaje. La causa más probable es que i y / o las variables que contengan el valor final se re-cargada de un desplazamiento fijo en la pila en cada iteración del bucle for, y su push compensa el puntero de pila desde donde el compilador espera que sea y por lo que hace que los valores incorrectos que ser recuperado.

Se podría intentar varias soluciones (por ejemplo, declarando la register variables locales), pero desafortunadamente no hay una buena manera de Garantía comportamiento correcto en C / C ++ en este caso. Para evitar el problema, implementar el bucle de sí mismo, como sugiere oivoodoo.

Aquí está mi esfuerzo de depuración psíquica:

i y this están más probable almacenan en la pila, y en las ubicaciones de memoria 386 y arriba, código de máquina se puede referir a esp-relativos directamente, por lo que el compilador bien pueden producir instrucciones como

mov eax,[esp+8]

para obtener el valor de this en el registro eax. El problema es que su desorden operaciones push con el puntero de pila, por lo que estos accesos no modificables accederán (cada vez más) posiciones de memoria equivocadas después de la primera iteración.

Lo más probable, las formas más simples de bucle sin this->someVar se optimizan más a fondo por el compilador y el resultado en código de máquina que utiliza sólo los registros y no hay accesos esp-relativo, lo que significa que siguen trabajando bien.

Había una vez, todos los accesos a memoria a las variables y argumentos locales se realizaron a través del registro ebp, que no cambia por su código ensamblador en línea. Si usted puede encontrar un interruptor compilador para forzar el uso de ebp en lugar de esp, esto puede resolver su problema.

Advertencia: el compilador no le esperaría que meterse con la pila - se espera que sepa en todo momento dónde la pila top-of-es. Si realmente quiere empujar de forma dinámica las cosas en la pila, sugeriría grabar el bucle por completo en lenguaje ensamblador como oivoodoo ha hecho.

En primer lugar, lo que está sucediendo es que, probablemente, gcc bajo Linux está utilizando el puntero de pila para indexar sus variables locales en lugar de utilizar el puntero del marco de pila. Esta es una optimización que permite gcc para usar el puntero de marco (BP bajo x86) como otro registro de propósito general y evitar una gran cantidad de código que establece marcos. Los marcos son esencialmente sólo la zona entre SP y BP que pertenecen a la función local. Apuesto a que si se incluye una llamada a alloca con un tamaño que le pasó a esta función sería todo mejorará, ya que obligaría a que el compilador no hacer esta optimización.

Una vez dicho esto, el error es realmente en el código. A menos que realmente sepa lo que está haciendo que nunca debe salir de un asm en línea con el puntero de pila diferente de lo que era cuando entró en el asm en línea. Los compiladores casi siempre piensan que poseen exclusivamente el puntero de pila. Ellos dependen de ello se mantiene igual para que puedan usarlo para encontrar donde se han almacenado variables. También debe mantenerse lejos del puntero de marco (BP).

Los tiempos en los que está bien meterse con aquellos son poco frecuentes y por lo general para cosas como contexto de código (el cambio de un hilo o proceso a otro) de conmutación.

Si conoce el límite en el número de argumentos, sólo puede llamar con una sola llamada de función con ese número de argumentos, la alineación de los argumentos reales hasta el final.

Advertencia: el abi x86_64 utiliza registrarse para algunos parámetros, que rompe esto y también el código

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