Rozszerzając Alexey:
Kiedy niektóre przerwania zdarzyć (ale nie inne), automatycznie pchania kod błędu 4 bajtów na stosie. Błąd strony jest jednym z nich.
Ten kod błędu zawiera dodatkowe informacje o przerwie.
Intel Manual Volume 3 System Programming Guide - 325384-056US September 2015 Tabela 6-1. Kolumna "Kod błędu" w "Protected-Mode Exceptions and Interrupts" dokładnie informuje, które przerwania powodują wypychanie kodu błędu, a które nie.
38.9.2.2 "Kody błędów strony" wyjaśnia, co oznacza błąd.
Więc trzeba będzie albo:
pop %eax
/* Do something with %eax */
iret
Lub jeśli chcesz zignorować kod błędu:
add $4, %esp
iret
za niewielką przykład patrz this page handler i spróbuj zakomentowałeś pop
.
Porównaj powyższe z Division error exception, który nie musi otwierać stosu.
Zauważ, że jeśli zrobisz po prostu int $14
, dodatkowy bajt nie zostanie zepchnięty: dzieje się tak tylko w przypadku rzeczywistego wyjątku.
Dobrym sposobem radzenia sobie z tym jest wypychanie na stosie fałszywego kodu błędu 0
dla przerwania, które nie powodują, że rzeczy są jednolite. Samouczek Jamesa Molloya: does exactly that.
Jądro 4.2 wydaje się robić coś podobnego. Pod arch/x86/entry/entry64.S modeli przerywa z has_error_code
:
trace_idtentry page_fault do_page_fault has_error_code=1
a następnie wykorzystuje je na tym samym pliku jako:
.ifeq \has_error_code
pushq $-1 /* ORIG_RAX: no syscall to restart */
.endif
który robi push gdy has_error_code=0
.
pytanie pokrewne: Do I have to pop the error code pushed to stack by certain exceptions before returning from the interrupt handler?
„To może być nie tak, bo nigdy nie (re) zainicjowany rejestru w trybie chronionym”, który rejestr powinien zainicjować? –
Wszystkie rejestry segmentów powinny być poprawnie zainicjowane w trybie chronionym (CS, DS, ES, SS, FS, GS). Właściwie to w tej chwili trudno powiedzieć, co jest nie tak, nie wiedząc więcej o kodzie. Opublikuj kod. –
Opis 'IRET' powinien dać ci kilka wskazówek, co może być nie tak. Spójrz na wszystkie warunki prowadzące do '#GP (selektor)'. –