2011-02-15 12 views
10

Mam pytanie dotyczące wyjątków EXCEPTION_INT_OVERFLOW i EXCEPTION_INT_DIVIDE_BY_ZERO.Win32 EXCEPTION_INT_OVERFLOW vs EXCEPTION_INT_DIVIDE_BY_ZERO

Windows przechwyci błędy #DE wygenerowane przez instrukcję IDIV i zakończy się generowaniem wyjątków SEH i jednym z tych dwóch kodów.

Mam pytanie, w jaki sposób rozróżnia się te dwa warunki? Informacje o idiv w podręczniku Intela wskazują, że wygeneruje #DE zarówno w "dzieleniu przez zero", jak i "przypadkach niedopełnienia".

Rzuciłem okiem na sekcję o błędzie #DE w tomie 3 podręcznika intel, a najlepsze, co mogłem zebrać, to to, że OS musi dekodować instrukcję DIV, ładując argument dzielnika, a następnie porównując to do zera.

Wydaje mi się to jednak trochę szalone. Dlaczego projektanci chipów nie używają jakiejś flagi do rozróżnienia dwóch przyczyn błędu? Czuję, że muszę czegoś przegapić.

Czy ktoś wie na pewno, w jaki sposób OS rozróżnia dwie różne przyczyny niepowodzenia?

+1

Czy posiadasz dokumentację wskazującą, że 'IDIV' może wytworzyć' EXCEPTION_INT_OVERFLOW'? Rozumiem, że 'INT_MIN/-1' jest problematyczne, ale opis' EXCEPTION_INT_OVERFLOW' nie zawiera tego przypadku. –

+0

@Ben zweryfikowałem to eksperymentalnie. Kiedy wykonuję INT_MIN/-1, instrukcja IDIV powoduje EXCEPTION_INT_OVERFLOW, a kiedy robię INT_MIN/0 otrzymuję EXCEPTION_INT_DIVIDE_BY_ZERO. W obu przypadkach wyjątek jest generowany po próbie wykonania instrukcji IDIV. –

+0

@Scotta: Hmmm ... Dokumentacja MSDN nie działa. Nie chodzi o to, że jest w tym coś niezwykłego. –

Odpowiedz

6

Twoje założenia wyglądają na prawidłowe. Jedyne informacje dostępne w #DE to CS i EIP, które przekazują instrukcję. Ponieważ oba kody stanu są różne, system operacyjny musi dekodować instrukcję, aby określić, która.

Sugerowałbym również, że producenci mikroukładów nie potrzebują dwóch oddzielnych przerwań dla tego przypadku, ponieważ wszystko podzielone przez zero to nieskończoność, która jest zbyt duża, aby zmieścić się w rejestrze docelowym.

Jeśli chodzi o "wiedząc na pewno", jak się różnicuje, wszyscy ci, którzy wiedzą, prawdopodobnie nie mogą tego ujawnić, aby zapobiec wykorzystywaniu przez nich (nie do końca pewni, jak to zrobić, ale przejście do trybu jądra to dobre miejsce aby zacząć wykorzystywać) lub przyjmując założenia na podstawie szczegółów wdrożenia, które mogą ulec zmianie bez powiadomienia.


Edit: Po zagraniu z kd mogę przynajmniej powiedzieć, że w konkretnej wersji systemu Windows XP (32-bit) miałem dostęp do (a procesor to biegł dalej) obsługi nt!Ki386CheckDivideByZeroTrap przerwań wydaje się dekodować wartość ModRM instrukcji, aby ustalić, czy zwrócić STATUS_INTEGER_DIVIDE_BY_ZERO lub STATUS_INTEGER_OVERFLOW.

(Oczywiście jest to oryginalne badania, nie są gwarantowane przez każdego w dowolnym miejscu, a także dzieje się dopasować odliczeń, które mogą być dokonane na podstawie Intela podręcznikach.)

+0

nie jestem naprawdę szuka czegoś innego niż zrozumieć, jak to jest realizowane. Wiem, że można to zaimplementować poprzez ręczne dekodowanie instrukcji i ładowanie argumentu, ale wydaje się to dziwnym sposobem na zrobienie tego. –

+0

@Scott Ponieważ procesor nie zapewnia żadnego sposobu wykrywania, oprócz dekodowania instrukcji, nie ma alternatywy. Doktorzy firmy Intel twierdzą, że nie ma modyfikacji stanu, a EIP nie jest nawet zaawansowany po instrukcji. Wyobrażam sobie, że jest więcej niż jeden przypadek, w którym jest to istotne (nielegalny opcode jest najbardziej prawdopodobny) i w każdym razie, dekodowanie wartości ModRM nie jest takie trudne - w jądrze znajdzie się funkcja, która to robi. – Zooba

+0

Wiem, że to nie jest trudne. Wydaje się, że jest to skuteczny sposób. Być może nie jest tak źle, w porównaniu do robienia spaceru na stosie. W każdym razie przeczytałem tę stronę (tę o #DE) w Podręczniku Intela i myślałem, że "muszą dekodować instrukcję, to jest interesujące". Chciałem się dowiedzieć, czy tak naprawdę to robi. –

1

odpowiedź Zooba za podsumowuje Windows analizuje instrukcji, aby dowiedzieć się co przebijać.

Nie można jednak polegać na tym, że procedura prawidłowo wybiera kod.

zaobserwowałem następujące w 64-bitowym systemie Windows 7 z 64-bitowych instrukcji DIV:

  • Jeśli operand (dzielnik) jest operand pamięci zawsze podnosi EXCEPTION_INT_DIVIDE_BY_ZERO, niezależnie od wartości argumentów.
  • Jeśli operand jest rejestrem, a dolny dword jest równy zero, podnosi EXCEPTATION_INT_DIVIDE_BY_ZERO niezależnie od tego, czy górna połowa nie jest równa zero.

Zajęło mi dzień, aby to znaleźć ... Mam nadzieję, że to pomaga.