¿El comportamiento indefinido se aplica al código asm?

5 minutos de lectura

Avatar de usuario de Eloff
Eloff

Digamos que sabe que su software solo se ejecutará en máquinas de complemento a dos donde el comportamiento de desbordamiento firmado está bien definido. El desbordamiento firmado sigue siendo un comportamiento indefinido en C y C++ y el compilador es libre de reemplazar todo su programa con “ret”, iniciar una guerra nuclear, formatear su disco o hacer que los demonios salgan volando de su nariz.

Supongamos que ha firmado un desbordamiento en asm en línea, ¿su programa aún invoca UB?

En caso afirmativo, ¿qué pasa con el ensamblador compilado y vinculado por separado?

  • Esta es una pregunta muy interesante. Quiero saber también.

    – callyalater

    1 de marzo de 2016 a las 18:32

  • ¿Asm en línea es incluso C o C++ estándar en primer lugar? Honestamente, no lo sé. Si no, toda la pregunta se encuentra en terreno inestable, creo.

    – Baum mit Augen

    1 de marzo de 2016 a las 18:33


  • Bueno, hay [dcl.asm]: los asm la declaración se apoya condicionalmente; su significado está definido por la implementación.

    – NathanOliver

    1 de marzo de 2016 a las 18:34


  • Para C99, lo único que encontré es sobre la palabra clave asm: J.5.10 La palabra clave asm se puede usar para insertar lenguaje ensamblador directamente en la salida del traductor (6.8).

    – fsasm

    1 de marzo de 2016 a las 18:44


  • Una gran cantidad de comportamiento indefinido está realmente definido por la implementación. “Comportamiento indefinido” no no significa “la implementación debe hacer que el comportamiento sea lo más aleatorio y malvado posible”.

    – Christian Hackel

    1 de marzo de 2016 a las 20:29

“Comportamiento indefinido” significa el C resp. Los estándares de C++ no definen el comportamiento de su programa. Si su programa contiene ensamblaje en línea, debe quedar bastante claro que su comportamiento normalmente no será descrito por el estándar C o C++. Algún otro estándar podría incluso definir el comportamiento, pero eso aún no significa “comportamiento definido” en el contexto del estándar C o C++.

Dicho esto, el estándar C requiere documentación de las extensiones admitidas. Si el comportamiento de su programa se puede inferir de la documentación de su implementación, y su implementación hace que su programa se comporte de manera diferente, eso es una falla de su implementación para cumplir con el estándar:

4. Conformidad

8 Una implementación debe ir acompañada de un documento que defina todas las características definidas por la implementación y específicas del lugar y todas las extensiones.

Para C++, este requisito se ha debilitado:

1.4 Cumplimiento de la implementación [intro.compliance]

9 Cada implementación deberá incluir documentación que identifique todas las construcciones soportadas condicionalmente que no soporta y define todas las características específicas de la localidad.

y

1.9 Ejecución del programa [intro.execution]

2 Ciertos aspectos y operaciones de la máquina abstracta se describen en esta Norma Internacional como definidos por la implementación. […] Cada implementación deberá incluir documentación que describa sus características y comportamiento en estos aspectos. […]

No puedo encontrar un requisito para que las extensiones se documenten y, si se documentan, se documenten correctamente. Esto sugeriría que en C++, incluso si su implementación define el comportamiento de su programa como una extensión, si resulta que la documentación es incorrecta, es una lástima.

Para el semiestándar de C++ asm declaración (como se menciona en los comentarios, “La asm la declaración se apoya condicionalmente; su significado está definido por la implementación”), si su implementación lo admite, debe documentarse, pero, por supuesto, es una práctica común que las implementaciones admitan el ensamblaje en línea de una manera diferente a la insinuada por el estándar C ++, por lo que esto no da usted mucho más.

  • Bien, de acuerdo con el estándar, su implementación se define en cuanto a lo que significa asm en línea para el programa. Esto plantea la pregunta entonces, ¿qué hacen realmente los compiladores populares?

    – Eloff

    1 de marzo de 2016 a las 19:01

  • @Eloff Esa es una pregunta muy diferente de lo que hizo en esta y requiere demasiado para responder aquí.

    usuario743382

    1 de marzo de 2016 a las 19:06

Tan pronto como diga que ha firmado el desbordamiento en asm en línea, significa que está hablando de un compilador particular (o un conjunto de compiladores) porque en C como en C ++, el soporte para la declaración de asm y su significado son compilador definido.

Si el compilador define la palabra clave asm al permitir la inclusión directa de código ensamblador en su salida y si la máquina permite el desbordamiento firmado, entonces un desbordamiento firmado en el asm en línea está perfectamente definido para ese compilador y esa máquina: es lo que dará como resultado el procesador. Aún debe controlar si puede resultar en una representación de trampa para un entero con signo, pero de todos modos es definido. El único caso que terminaría en UB sería cuando el compilador dice que alguna representación en un entero con signo causará un comportamiento indefinido. Pero no conozco ninguno que lo haga y ya estás en el contexto de un conjunto definido y finito de compiladores y máquinas.

La compilación separada de un módulo ensamblador y el código C y/o C++ sería lo mismo para ese conjunto de compiladores y máquinas: el resultado es implementación definida que no es lo mismo que UB.

Otro ejemplo de algo que está explícitamente definido en la implementación de los estándares (tanto C como C++) es si char el tipo está firmado o no: si no sabe qué compilador usa, no puede confiar en él, pero tan pronto como elija una implementación del compiladorse requiere que la implementación diga si está firmada o no, y es no comportamiento indefinido, lo que significa que el compilador no puede reemplazar el código completo con un ret, por ejemplo.

¿Ha sido útil esta solución?