में वास्तविक से सुरक्षित मोड से संक्रमण मैं वर्तमान में ऑपरेटिंग सिस्टम के निम्न स्तर के संगठन का अध्ययन कर रहा हूं। यह स्वीकार करने के लिए कि मैं समझने की कोशिश कर रहा हूं कि लिनक्स कर्नेल कैसे लोड किया जाता है।लिनक्स कर्नेल
एक चीज जिसे मैं समझ नहीं पा रहा हूं वह 16-बिट (वास्तविक मोड) से 32-बिट (संरक्षित मोड) में संक्रमण है। यह this file में होता है।
protected_mode_jump
समारोह है कि बाद में मार डाला है 32-बिट कोड के लिए विभिन्न सहायक गणना करता है, तो CR0
reguster
movl %cr0, %edx
orb $X86_CR0_PE, %dl # Protected mode
movl %edx, %cr0
में PE
बिट सक्षम बनाता है और उसके बाद 32-बिट कोड के लिए लंबी कूद करता है:
# Transition to 32-bit mode
.byte 0x66, 0xea # ljmpl opcode
2: .long in_pm32 # offset
.word __BOOT_CS # segment
जहां तक मेरा in_pm32
समझते हैं जो सही protected_mode_jump
नीचे घोषित किया जाता है 32-बिट समारोह का पता है:
.code32
.section ".text32","ax"
GLOBAL(in_pm32)
# some code
# ...
# some code
ENDPROC(in_pm32)
__BOOT_CS
क्षेत्र आधार 0 (GDT पहले से here सेट किया गया है), तो यह है कि इसका मतलब है कि ऑफसेट in_pm32
समारोह के मूल रूप से पूर्ण पता होना चाहिए।
यह मुद्दा है। मशीन कोड पीढ़ी के दौरान असेंबलर/लिंकर को in_pm32
फ़ंक्शन का पूर्ण पता नहीं पता होना चाहिए, क्योंकि यह नहीं जानता कि यह वास्तविक मोड में स्मृति में कहां लोड किया जाएगा (विभिन्न बूटलोडर्स अंतरिक्ष की विभिन्न मात्रा और वास्तविक मोड पर कब्जा कर सकते हैं कर्नेल को बूटलोडर के ठीक बाद लोड किया जाता है)।
इसके अलावा, लिंकर स्क्रिप्ट (setup.ld
एक ही फ़ोल्डर में) कोड की उत्पत्ति 0 के रूप में सेट करता है, ऐसा लगता है कि in_pm32
पता वास्तविक मोड कर्नेल की शुरुआत से ऑफ़सेट होगा। इसे 16-बिट कोड के साथ ठीक काम करना चाहिए क्योंकि CS
रजिस्टर ठीक से सेट किया गया है, लेकिन जब लंबी कूद होती है तो सीपीयू पहले से ही सुरक्षित मोड में है, इसलिए एक रिश्तेदार ऑफसेट काम नहीं करना चाहिए।
तो मेरे सवाल: क्यों संरक्षित मोड (.byte 0x66, 0xea
) में लंबी कूद उचित कोड स्थिति सेट करता है, तो ऑफसेट (.long in_pm32
) रिश्तेदार है करता है?
ऐसा लगता है कि मुझे कुछ वाकई महत्वपूर्ण याद आ रहा है।
मैं बिस्तर पर जाने वाला हूं क्योंकि यह 3:30 बजे है। मैंने केवल जेएमपी के बारे में हिस्सा देखा। वह कूद एक 32-बिट एफएआर जेएमपी है जो _CS_ चयनकर्ता सेट करता है। सीआर 0 में संरक्षित मोड बिट को सेट करना वास्तव में आपको एक अर्ध 16-बिट संरक्षित मोड में डाल देता है। 32-बिट संरक्षित मोड में जाने के लिए आपको एक एफएआर जेएमपी करना होगा जो एक चयनकर्ता (__BOOT_CS) और ऑफसेट लेता है और उस पर कूदता है। __BOOT_CS एक चयनकर्ता होना चाहिए जो जीडीटी में 32-बिट कोड सेगमेंट डिस्क्रिप्टर (0 के आधार और 0xffffffff की सीमा के साथ) पर इंगित करता है। जब वह एफएआर जेएमपी पूरा हो जाए तो यह 32-बिट संरक्षित मोड में होगा। –
संक्षेप में कि एफएआर जेएमपी को अर्ध 16-बिट संरक्षित मोड से 32-बिट संरक्षित मोड में प्राप्त करने की आवश्यकता है। –
वास्तव में, '__BOOT_CS' चयनकर्ता आधार 0 है। मुझे लगता है कि इसका मतलब है कि FAR JUMP को वांछित फ़ंक्शन/लेबल का पूर्ण पता लेना चाहिए (क्योंकि' 0 + ऑफ़सेट 'केवल' ऑफ़सेट' होगा)। लेकिन यहां पर एफएआर जंप को सापेक्ष ऑफसेट ('.long in_pm32'' वास्तविक मोड कर्नेल बाइनरी की शुरुआत से 'in_mp32' फ़ंक्शन का पता है) के साथ बुलाया जाता है - और मुझे समझ में नहीं आता कि अंत में 'in_pm32' फ़ंक्शन क्यों निष्पादित किया जाता है। दूर की कूद 0x7C00 + bootloader_size बाइट्स पर मेल नहीं खाई जानी चाहिए। – Alexander