संरक्षित मोड के लिए इंटरप्ट सेट करने की प्रक्रिया क्या है?संरक्षित मोड में इंटरप्ट्स सेट करना (x86)
This लिंक कहते हैं एक चाहिए::
- बाधा डिस्क्रिप्टर तालिका
- के लिए मेक अंतरिक्ष सीपीयू जहां कि अंतरिक्ष है (lidt lgdt के रूप में बहुत उसी तरह काम करता देख GDT ट्यूटोरियल) बताओ
- पीआईसी को बताएं कि अब आप BIOS डिफ़ॉल्ट का उपयोग नहीं करना चाहते हैं (पीआईसी चिप्स प्रोग्रामिंग देखें)
- आईआरक्यू और अपवाद दोनों के लिए कुछ आईएसआर हैंडलर (इंटरप्ट सेवा रूटीन देखें) लिखें
- उचित वर्णनकर्ता
- आईआरक्यू नकाब में सभी समर्थित बीच में आता है (पीआईसी की)
तीसरे चरण में मेरे लिए कोई मतलब नहीं है सक्षम करें (मैं को देखा में ISR संचालकों के पते रखो this लिंक लेकिन पीआईसी को कुछ भी बताने के बारे में कुछ भी नहीं था) इसलिए मैंने इसे अनदेखा कर दिया और अगले दो चरणों को पूरा किया, केवल एक बार फिर जब मैं अंतिम चरण तक पहुंचा तो अनजान हो गया। हालांकि, इंटरप्ट्स की मेरी समझ से, दोनों चरणों को मैं समझ नहीं पाया था कि पीआईसी नियंत्रक से हार्डवेयर इंटरप्ट्स से संबंधित है और आईआरक्यू 0 पर पीआईटी द्वारा उठाए गए इंटरप्ट को प्रभावित नहीं करना चाहिए। इसलिए मैंने इस चरण को भी नजरअंदाज कर दिया।
जब मैंने अपना कोड चलाया तो यह ठीक हो गया और वर्चुअल मशीन में भी भाग गया, लेकिन अंतराल केवल एक बार आग लग रहा था। तब मुझे एहसास हुआ कि मैं पीआईसी को ईओआई नहीं भेज रहा था, इसे और अधिक बाधाओं को बढ़ाने से रोक रहा था। हालांकि, निर्देश से पहले mov al, 0x20
और out 0x20, al
जोड़ना निर्देश वर्चुअल मशीन क्रैश बनाता है।
; idt
idt_start :
dw 0x00 ; The interrupt handler is located at absolute address 0x00
dw CODE_SEG ; CODE_SEG points to the GDT entry for code
db 0x0 ; The unused byte
db 0b11101001 ; 1110 Defines a 32 bit Interrupt gate, 0 is mandatory, privilege level = 0 (0b00), the last bit is one so that the CPU knows that the interrupt will be used
dw 0x00 ; The higher part of the offset (0x00) is 0x00
idt_end:
idt_descriptor :
dw idt_end - idt_start - 1 ; Size of our idt, always one less than the actual size
dd idt_start ; Start address of our idt
यहाँ मेरी बाधा हैंडलर (स्मृति में पूर्ण स्थान 0x00 पर स्थित) है:
यहाँ मेरी IDT है
ISR_0:
push eax
add [0x300], byte
mov al, 0x20
out 0x20, al
pop eax
iret
times 512-($-$$) db 0
इस कोड मैं सुरक्षित मोड में प्रवेश करने और GDT लोड करने के लिए उपयोग करें और आईडीटी में स्मृति:
[bits 16]
switch_to_pm:
cli
lgdt [gdt_descriptor]
lidt [idt_descriptor]
mov eax, cr0
or eax, 1
mov cr0,eax
jmp CODE_SEG:init_pm
[bits 32]
init_pm :
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
sti
call BEGIN_PM
मेरा मुख्य कार्य (जो 0x300 के मान की जांच करता है) निम्नानुसार है:
void main() {
char iii[15];
int * aa = (int *)0x300;
for (;;)
{
setCursor(0, 0);
print(itoab(*aa, iii));
}
}
वैसे, मैं एक स्मृति डंप का उपयोग कर कि सब कुछ सही पते पर लोड किया जाता है और सब कुछ बिल्कुल जहां यह उम्मीद है है सत्यापित किया है। उदाहरण के लिए, 0x300 बस मेरे कोड को सरल बनाने के लिए उपयोग की गई स्मृति का एक नि: शुल्क हिस्सा है।
तीसरे चरण उनके मानक BIOS मैपिंग से बीच में आता है remapping के सामान्य प्रक्रिया को संदर्भित करता है: यह
/asm/system.h
में इस प्रकार परिभाषित किया गया है। आम तौर पर आईआरक्यू 0-7 को आईएनटी 8-15 में मैप किया जाता है, और आईआरक्यू 8-15 को आईएनटी 0x70-0x77 में मैप किया जाता है। पूर्व मैपिंग में समस्या आई है क्योंकि आईएनटी 8-15 में कई सीपीयू अपवाद हैं, इसलिए अधिकांश ऑपरेटिंग सिस्टम कम से कम आईआरक्यू 0-7 को सीपीयू अपवाद –के लिए आरक्षित सीमा के बाहर रीमेप करते हैं ध्यान दें कि इसका अर्थ है पीआईटी , जो आईआरक्यू 0 से जुड़ा हुआ है, INT 8. उत्पन्न करता है INT 0 पूर्णांक विभाजित ओवरफ़्लो (शून्य से विभाजित) अपवाद है। –
आईआरक्यू की पहली 32 आईडीटी प्रविष्टियों के ऊपर जाने के लिए चरण 3 करने की अत्यधिक अनुशंसा की जाती है, क्योंकि इन्हें जाल के लिए उपयोग किया जाता है। मैं उन पहले 32 के लिए कुछ हैंडलर डालने की अत्यधिक अनुशंसा करता हूं, ताकि आप देख सकें कि क्या आप किसी समस्या में भाग लेते हैं या नहीं। [और अपने एए चर के लिए volatiled उपयोग करें! –