2011-02-15 7 views
10

Tengo una pregunta acerca de las excepciones EXCEPTION_INT_OVERFLOW y EXCEPTION_INT_DIVIDE_BY_ZERO.Win32 EXCEPTION_INT_OVERFLOW frente a EXCEPTION_INT_DIVIDE_BY_ZERO

Windows interceptará los errores #DE generados por la instrucción IDIV y terminará generando y la excepción SEH con uno de esos 2 códigos.

La pregunta que tengo es ¿cómo se diferencia entre las dos condiciones? La información sobre idiv en el manual de Intel indica que generará #DE tanto en "divide por cero" como en "casos de subdesbordamiento".

Eché un vistazo rápido a la sección sobre el error #DE en el Volumen 3 del manual de Intel, y lo mejor que pude deducir es que el sistema operativo debe decodificar la instrucción DIV, cargar el argumento del divisor y luego comparar a cero

Eso me parece un poco loco. ¿Por qué los diseñadores de chips no usarían una bandera de algún tipo para diferenciar entre las 2 causas del error? Siento que debo estar perdiendo algo.

¿Alguien sabe con certeza cómo el SO diferencia entre las 2 causas diferentes de falla?

+1

¿Tiene alguna documentación que indique que 'IDIV' incluso puede producir' EXCEPTION_INT_OVERFLOW'? Entiendo que 'INT_MIN/-1' es problemático, pero la descripción de' EXCEPTION_INT_OVERFLOW' no parece incluir este caso. –

+0

@Ben Lo verifiqué experimentalmente. Cuando hago INT_MIN/-1, la instrucción IDIV da como resultado un EXCEPTION_INT_OVERFLOW, y cuando hago INT_MIN/0 obtengo EXCEPTION_INT_DIVIDE_BY_ZERO. En ambos casos, la excepción se produce después de intentar la ejecución de la instrucción IDIV. –

+0

@Scott: Hmmm ... Falla la documentación de MSDN. No es que haya algo inusual en eso. –

Respuesta

6

Sus suposiciones parecen ser correctas. La única información disponible en #DE es CS y EIP, que proporciona la instrucción. Como los dos códigos de estado son diferentes, el sistema operativo debe decodificar la instrucción para determinar cuál.

También sugiero que los fabricantes de chips realmente no necesiten dos interrupciones separadas para este caso, ya que cualquier cosa dividida por cero es infinito, que es demasiado grande para caber en su registro de destino.

En cuanto a "saber con certeza" cómo se diferencia, todos aquellos que lo conocen probablemente no puedan revelarlo, ya sea para evitar que la gente lo explote (no del todo seguro, pero saltar al modo núcleo es un buen lugar para comenzar a buscar explotar) o hacer suposiciones basadas en un detalle de implementación que puede cambiar sin previo aviso.


Editar: haber tocado con kd al menos puedo decir que en la versión de Windows XP (32 bits) que tenía acceso a (y el procesador que se ejecutan en) el manejador nt!Ki386CheckDivideByZeroTrap interrupción parece decodificar el valor ModRM de la instrucción para determinar si se devuelve STATUS_INTEGER_DIVIDE_BY_ZERO o STATUS_INTEGER_OVERFLOW.

(Obviamente, esto es una investigación original, no está garantizada por cualquier persona en cualquier lugar, y también pasa a coincidir con las deducciones que se pueden hacer sobre la base de los manuales de Intel.)

+0

No estoy buscando nada, aparte de comprender cómo se implementa. Sé que puede implementarse decodificando manualmente las instrucciones y cargando el argumento, pero parece una extraña forma de hacerlo. –

+0

@Scott Dado que el procesador no proporciona ninguna forma de detectarlo aparte de decodificar las instrucciones, no hay otra alternativa. Los documentos de Intel dicen que no se produce ninguna modificación de estado, y EIP ni siquiera avanza más allá de la instrucción. Imagino que hay más de un caso donde esto es relevante (el código de operación ilegal es el más probable) y, en cualquier caso, la decodificación de un valor ModRM no es tan difícil; habrá una función en el kernel que lo haga. – Zooba

+0

Sé que no es difícil. Simplemente parece una forma eficiente de hacerlo. Tal vez no es tan malo, en comparación con hacer una caminata de pila. En cualquier caso, leí esa página (la de #DE) en el Manual de Intel y pensé "deben decodificar las instrucciones, eso es interesante". Quería saber si eso es lo que realmente estaba haciendo. –

1

respuesta de Zooba resume el Windows analiza la instrucción para averiguar que subir

Pero no puede confiar en que la rutina elige correctamente el código.

que observar lo siguiente en 64 bits de Windows 7 con las instrucciones DIV 64 bits:

  • Si el operando (divisor) es un operando de memoria que siempre plantea EXCEPTION_INT_DIVIDE_BY_ZERO, independientemente del valor del argumento.
  • Si el operando es un registro y el dword inferior es cero, aumenta EXCEPTION_INT_DIVIDE_BY_ZERO independientemente de si la mitad superior no es cero.

Me llevó un día descubrir esto ... Espero que esto ayude.

Cuestiones relacionadas