किसी भाषा का विस्तार कैसे होता है? [बन्द है]


208

मैं C ++ सीख रहा हूं और मैंने GUI प्रोग्राम कोड करने के लिए Qt की कुछ क्षमताओं के बारे में सीखना शुरू कर दिया है । मैंने खुद से निम्नलिखित प्रश्न पूछा:

C ++ कैसे करता है, जो पहले कोई सिंटैक्स नहीं था जो ओएस को एक खिड़की या नेटवर्क के माध्यम से संचार करने के लिए सक्षम करने के लिए सक्षम था (एपीआई के साथ जो मुझे पूरी तरह से समझ में नहीं आता है, मैं मानता हूं) अचानक सी ++ में लिखी गई पुस्तकालयों के माध्यम से खुद को ऐसी क्षमताएं मिलती हैं? यह सब मुझे बहुत बड़ा लगता है। आप उन पुस्तकालयों में संभवतः C ++ के निर्देश क्या दे सकते हैं?

मुझे लगता है कि यह सवाल एक अनुभवी सॉफ्टवेयर डेवलपर के लिए मामूली लग सकता है, लेकिन मैं बिना किसी प्रत्यक्ष प्रतिक्रिया के घंटों तक शोध कर रहा हूं। यह उस बिंदु पर पहुंच गया है जहां मैं Qt के बारे में ट्यूटोरियल का पालन नहीं कर सकता क्योंकि पुस्तकालयों का अस्तित्व मेरे लिए समझ से बाहर है।


27
कैसे std :: cout भी मॉनिटर पर कुछ भी आकर्षित करता है? या यह एक कंपाइलर के ऊपर बैठता है जो आपके हार्डवेयर को समझता है?
डॉक्टरलॉव

14
बड़ा सवाल है। अंततः जब तक आप हार्डवेयर का अध्ययन नहीं करते तब तक उत्तर देना कठिन है।
user541686

17
क्यूटी भाषा का विस्तार नहीं है (इसके लिए क्यूटी-जागरूक कंपाइलर की आवश्यकता होगी)। यह केवल एक पुस्तकालय है जो आपके शस्त्रागार में जोड़ा जाता है। आखिरकार, सबसे निचले स्तर पर सभी लाइब्रेरी सिस्टम कॉल के माध्यम से ओएस के साथ संवाद करते हैं, जो भाषा से स्वतंत्र हैं, लेकिन बहुत ओएस और सीपीयू वास्तुकला पर निर्भर हैं।
DevSolar

8
afaik, C ++ में इनलाइन असेंबली है, जो बहुत कुछ कर सकती है
प्रदर्शन नाम

9
@DevSolar: वास्तव में क्यूटी अपने स्वयं के सिग्नल-स्लॉट तंत्र, प्रतिबिंब और कई अन्य गतिशील सुविधाओं के साथ भाषा का विस्तार करता है। और उन चीजों को C ++ कोड के संकलन के लिए एक कंपाइलर (मेटा-ऑब्जेक्ट कंपाइलर) की आवश्यकता होती है।
सियुआन रेन

जवाबों:


194

एक कंप्यूटर एक प्याज की तरह होता है, इसमें कई सारी परतें होती हैं, जो शुद्ध हार्डवेयर के आंतरिक कोर से सबसे बाहरी अनुप्रयोग परत तक होती है। प्रत्येक परत अगले बाहरी परत के लिए अपने आप को उजागर करती है, ताकि बाहरी परत आंतरिक परतों की कार्यक्षमता का उपयोग कर सके।

उदा। विंडोज के मामले में ऑपरेटिंग सिस्टम विंडोज पर चलने वाले एप्लिकेशन के लिए तथाकथित Win32 एपीआई को उजागर करता है। Qt लाइब्रेरी अपने API से Qt का उपयोग करके एप्लिकेशन प्रदान करने के लिए उस API का उपयोग करती है। आप Qt का उपयोग करते हैं, Qt Win32 का उपयोग करता है, Win32 विंडोज ऑपरेटिंग सिस्टम के निचले स्तर का उपयोग करता है, और इसी तरह जब तक यह हार्डवेयर में इलेक्ट्रिकल सिग्नल नहीं होता है।


56
नोट: Qtयहाँ नीचे परत की एक अमूर्तता प्रदान करता है, क्योंकि लिनक्स पर Qtलिनक्स एपीआई और विन 32 एपीआई नहीं है।
Matthieu M.

5
मैं शायद क्यूटी के उदाहरण पर थोड़ा और अधिक लिखूंगा, कि यह बस दिखाई देता है, जैसे यह आसानी से सी ++ क्षमताओं का विस्तार करता है। जब वास्तविकता होती है, तो वे एक आम एपीआई बनाने के लिए, (डिबेटीली) कई अलग-अलग "प्याज कोरल" बनाने के लिए बहुत प्रयास करते हैं। वे गैर-पोर्टेबल गैर-मानक बैकएंड के शीर्ष पर पोर्टेबिलिटी प्रदान करते हैं।
luk32

81
एक कंप्यूटर एक प्याज की तरह है: इसके माध्यम से काटने से आप रोते हैं, लेकिन यह बाद में कुछ स्वादिष्ट है।
एलेकोव

3
@ChristopherPfohl हाँ, मुझे इसका इस्तेमाल करना पड़ा क्योंकि मैं यह पता नहीं लगा सकता था कि एक कंप्यूटर चॉकलेट के बक्से की तरह कैसे होगा। :)
कुछ प्रोग्रामर

1
@Celeritas शिक्षक ने शायद कहा user32.dll, या संभवतः gdi32.dll
user253751

59

आप सही हैं कि सामान्य तौर पर, पुस्तकालय कुछ भी संभव नहीं बना सकते हैं जो पहले से संभव नहीं है।

लेकिन C ++ प्रोग्राम द्वारा प्रयोग करने योग्य होने के लिए पुस्तकालयों को C ++ में नहीं लिखा जाना चाहिए। यहां तक ​​कि अगर वे C ++ में लिखे गए हैं, तो वे आंतरिक रूप से C ++ में नहीं लिखे गए अन्य पुस्तकालयों का उपयोग कर सकते हैं। इसलिए तथ्य यह है कि C ++ ने इसे करने का कोई तरीका प्रदान नहीं किया है, इसे जोड़े जाने से नहीं रोकता है, इसलिए जब तक कि C ++ के बाहर इसे करने का कोई तरीका नहीं है।

काफी निम्न स्तर पर, C ++ द्वारा (या C) कहे जाने वाले कुछ फ़ंक्शन असेंबली में लिखे जाएंगे, और असेंबली में C ++ में जो भी संभव नहीं है (या आसान नहीं है) करने के लिए आवश्यक निर्देश हैं, उदाहरण के लिए कॉल एक सिस्टम फ़ंक्शन। उस बिंदु पर, वह सिस्टम कॉल कुछ भी कर सकता है जो आपके कंप्यूटर में सक्षम है, बस क्योंकि इसमें कुछ भी नहीं है।


क्या आपका मतलब है कि अन्य भाषाओं में लिखी गई लाइब्रेरियों को पहले से ही अन्य संकलक का उपयोग करके संकलित किया गया है? और फिर कुछ प्रकार की इंटरफ़ेस फ़ाइल होनी चाहिए जो लाइब्रेरी द्वारा लाइब्रेरी के पहले से तैयार किए गए संस्करण में C ++ को प्रदान किए गए प्रत्येक फ़ंक्शन कॉल को लिंक करती हो? इस प्रकार सी + + संकलक को यह जानने की अनुमति देता है कि उन कॉलों का अनुवाद क्या है?
मेड लार्बी सेंटीसी जूल

2
@MedLarbiSentissi 1) जरूरी नहीं कि अन्य कंपाइलर। यह संभव है (और ऐसा ही होता है, अक्सर) यह है कि एक एकल संकलक असेंबली सहित कई भाषाओं को संकलित करने में सक्षम है, और यह इनलाइन असेंबली के साथ C ++ को संकलित करने में भी सक्षम हो सकता है। 2) विशिष्ट प्रणाली और संकलक के आधार पर, उन कार्यों को C ++ से कॉल करने योग्य बनाया जा सकता है जो वास्तव में किसी प्रकार की इंटरफ़ेस फ़ाइल के साथ किया जा सकता है, लेकिन उस प्रकार की इंटरफ़ेस फ़ाइल पहले से ही C ++ से सीधे उपयोग योग्य C (या C ++) हेडर हो सकती है।

1
@MedLarbiSentissi: कई विंडोज़ लाइब्रेरी को dll फ़ाइलों में संकलित किया गया है, जिसमें अपना स्वयं का इंटरफ़ेस, साथ ही कोड भी होते हैं। आप एक dll में जा सकते हैं और उन कार्यों की एक सूची देख सकते हैं जो आपको उपयोग करने देता है। वे अक्सर सी हेडर फ़ाइल के साथ भी आते हैं। जब आप अपना exe बनाते हैं, तो इसमें उन dlls की एक सूची होती है, जिन्हें इसे चलाने की आवश्यकता होती है। जब OS आपके exe को लोड करने की कोशिश करता है, तो यह निष्पादन शुरू करने से पहले स्वचालित रूप से उन dll को भी लोड कर देगा।
मूइंग डक

8
यह उत्तर बताता है कि "जादू" पूरी तरह से अन्य भाषाओं में कहा जा रहा है, लेकिन वास्तव में अधिकांश कोड जो अधिकांश आधुनिक ऑपरेटिंग सिस्टम का गठन करते हैं, वह है C (केवल बहुत ही हार्डवेयर-बंधे या प्रदर्शन-महत्वपूर्ण भागों को विधानसभा में लिखा गया है) - और इसके बजाय C ++ का उपयोग करना निश्चित रूप से संभव है। मुद्दा यह है कि, कोई "जादू" नहीं है, इस तरह के शक्तिशाली सार बनाने के लिए भाषाएं बनाई जाती हैं, और एक बार जब आप हार्डवेयर के साथ बातचीत कर सकते हैं तो संभावनाएं लगभग असीम होती हैं।
मत्तेओ इटालिया

1
@ मुझे लगता है कि इस चर्चा में पूरा संघर्ष यह है कि आप (और अन्य) सी को उन विशेषताओं के रूप में परिभाषित करते हैं जो इसके लिए निर्दिष्ट हैं। वास्तव में, कंपाइलर जो निर्दिष्ट किया गया है, उससे बहुत अधिक जोड़ते हैं, जिससे यह सवाल बनता है कि C उत्तर देने के लिए थोड़े गैर-तुच्छ है। मेरे लिए एक भाषा के बारे में विशेष बात (इस प्रकार यह है कि) एक्सप्रेसस्प्रेमग्राम प्रवाह और संरचना की संभावनाओं के लिए मेटा-वे है। जो तत्व संरचित हैं, वे इसके लिए महत्वपूर्ण नहीं हैं, क्योंकि यह सिर्फ एएसएम-कोड है जिसे संकलक द्वारा जोड़ा जा सकता है जैसे वे चाहते हैं
LionC

43

C और C ++ में 2 गुण हैं जो ओपी के बारे में बात करने वाले इस सभी विस्तार की अनुमति देते हैं।

  1. C और C ++ मेमोरी को एक्सेस कर सकते हैं
  2. C और C ++ निर्देश कोड को C या C ++ भाषा में नहीं के लिए असेंबली कोड कह सकते हैं।

कर्नेल में या एक बुनियादी गैर-संरक्षित मोड प्लेटफ़ॉर्म में, सीरियल पोर्ट या डिस्क ड्राइव जैसे परिधीय मेमोरी मैप में उसी तरह मैप किए जाते हैं जैसे रैम है। मेमोरी स्विच की एक श्रृंखला है और परिधीय के स्विच को फ्लिप करता है (जैसे सीरियल पोर्ट या डिस्क ड्राइवर) उपयोगी चीजें करने के लिए आपका परिधीय हो जाता है।

एक संरक्षित मोड ऑपरेटिंग सिस्टम में, जब कोई यूजरस्पेस से कर्नेल को एक्सेस करना चाहता है (जैसे कि फाइल सिस्टम पर लिखते समय या स्क्रीन पर एक पिक्सेल खींचने के लिए) किसी को सिस्टम कॉल करने की आवश्यकता होती है। C के पास सिस्टम कॉल करने के लिए निर्देश नहीं है लेकिन C असेंबलर कोड को कॉल कर सकता है जो सही सिस्टम कॉल को ट्रिगर कर सकता है, यही वह है जो किसी C कोड को कर्नेल से बात करने की अनुमति देता है।

प्रोग्रामिंग को एक विशेष प्लेटफॉर्म को आसान बनाने के लिए, सिस्टम कॉल्स को और अधिक जटिल कार्यों में लपेटा जाता है जो किसी के स्वयं के कार्यक्रम में कुछ उपयोगी कार्य कर सकते हैं। एक सिस्टम कॉल को सीधे कॉल करने के लिए स्वतंत्र है (कोडांतरक का उपयोग करके) लेकिन प्लेटफॉर्म की आपूर्ति करने वाले आवरण कार्यों में से किसी एक का उपयोग करना आसान है।

एपीआई का एक और स्तर है जो एक सिस्टम कॉल की तुलना में बहुत अधिक उपयोगी है। उदाहरण के लिए ले लो। यह न केवल सिस्टम को मेमोरी के बड़े ब्लॉक प्राप्त करने के लिए बुलाएगा, बल्कि इस मेमोरी को प्रबंधित करेगा कि यह क्या हो रहा है।

Win32 एपीआई एक सामान्य मंच विजेट सेट के साथ कुछ ग्राफिक कार्यक्षमता लपेटते हैं। Qt इसे Win32 (या X विंडोज) एपीआई को क्रॉस प्लेटफॉर्म तरीके से लपेटकर थोड़ा आगे ले जाता है।

मौलिक रूप से, हालांकि एक सी कंपाइलर सी कोड को मशीन कोड में बदल देता है और चूंकि कंप्यूटर को मशीन कोड का उपयोग करने के लिए डिज़ाइन किया गया है, इसलिए आपको उम्मीद करनी चाहिए कि सी शेर के हिस्से को पूरा करने में सक्षम हो या कंप्यूटर क्या कर सकता है। रैपर लाइब्रेरी जो सभी करते हैं, वह आपके लिए भारी लिफ्टिंग है, ताकि आपके पास न हो।


# 2 के बारे में चेतावनी: C और C ++ केवल व्यावहारिक रूप से कॉल फ़ंक्शन कर सकते हैं जो एक "कॉलिंग कन्वेंशन" का पालन करते हैं जिसे कंपाइलर समझता है और उम्मीद करता है। (असेंबली कोड किसी भी सम्मेलन का उपयोग कर सकता है जिसे वह पसंद करता है, या यहां तक ​​कि कोई भी नहीं - इसलिए कोड सीधे कॉल करने योग्य नहीं हो सकता है।) सौभाग्य से, प्रत्येक स्वाभिमानी कंपाइलर प्लेटफ़ॉर्म के आम सम्मेलनों का उपयोग करने के लिए एक अंतर्निहित तरीका प्रदान करता है। (विंडोज सी कंपाइलर, उदाहरण के लिए, आपके पास "cdecl", "stdcall", या "fastcall" सम्मेलनों का उपयोग करने वाले फ़ंक्शन हैं / उपयोग करें।) लेकिन असेंबली कोड को एक कन्वेंशन का उपयोग करना चाहिए जिसे कंपाइलर जानता है, या C और C ++ '। t इसे सीधे कॉल करें।
cHao

2
इसके अलावा: मेमोरी-मैप्ड I / O आम है, लेकिन पूरी कहानी नहीं। पीसी, उदाहरण के लिए, आमतौर पर सीरियल पोर्ट, डिस्क ड्राइव आदि को x86 के "I / O पोर्ट्स" का उपयोग करके संबोधित करते हैं, जो एक पूरी तरह से अलग तंत्र है। (वीडियो बफर आमतौर पर मेमोरी मैप्ड होता है, लेकिन वीडियो मोड आदि को आमतौर पर I / O पोर्ट के माध्यम से नियंत्रित किया जाता है।)
cHao

@cHao: बेशक INP और OUTP का उपयोग कर क्लासिक दृष्टिकोण DMA के पक्ष में समाप्त हो रहा है; पीसीआई पीढ़ी मेमोरी-मैप्ड विशेष फ़ंक्शन रजिस्टरों के साथ अधिक करने लगती है, अब गैर-अतिव्यापी क्षेत्रों में उपकरणों को स्वचालित रूप से मैप करने और ड्राइवरों से उन्हें खोजने का एक तरीका है, और I / O बंदरगाहों के साथ कम है।
बेन वोइगट

आधुनिक परिधीय थोक डेटा ट्रांसफर के लिए डीएमए का उपयोग करेंगे, लेकिन आप अभी भी डीएएमए कंट्रोलर को संबोधित करने योग्य मेमोरी के साथ प्रोग्राम करेंगे
डॉरन जूल 29'14

@ डोरॉन: उम्म, आप एक पीसी पर आई / ओ एड्रेस स्पेस (मेमोरी स्पेस नहीं) के माध्यम से डीएमए कंट्रोलर प्रोग्राम करते हैं, कम से कम अगर आप समझदार हैं। आधुनिक x86 CPUs प्रदर्शन सुधारने के लिए मेमोरी एक्सेस को फिर से चालू करना पसंद करते हैं। MMIO के साथ, यह विनाशकारी हो सकता है ... इसलिए आपको उन पते को अनचेक करने और सभी सही स्थानों पर क्रमबद्ध निर्देश डालने के लिए सावधान रहने की आवश्यकता होगी । OTOH, x86 ही सुनिश्चित करता है कि कार्यक्रम क्रम में I / O स्थान पर लिखा और लिखा जाए। यही कारण है कि बहुत से महत्वपूर्ण सामान अभी भी I / O अंतरिक्ष के माध्यम से किया जाता है (जो आमतौर पर एक पॉइंटर के माध्यम से सुलभ नहीं है), और शायद हमेशा रहेगा।
cHao

23

भाषाएँ (जैसे C ++ 11 ) विशिष्टताओं हैं , कागज पर, आमतौर पर अंग्रेजी में लिखी जाती हैं। नवीनतम C ++ 11 ड्राफ्ट के अंदर देखें (या अपने आईएसओ विक्रेता से महंगा अंतिम चश्मा खरीदें )।

आप आम तौर पर कुछ भाषा कार्यान्वयन के साथ एक कंप्यूटर का उपयोग करते हैं (आप सिद्धांत रूप में किसी भी कंप्यूटर के बिना एक C ++ प्रोग्राम चला सकते हैं, उदाहरण के लिए मानव दासों के एक समूह का उपयोग करते हुए; यह अनैतिक और अक्षम होगा)

आपका C ++ कार्यान्वयन सामान्य कुछ ऑपरेटिंग सिस्टम के ऊपर काम करता है और इसके साथ संचार करता है (कुछ कार्यान्वयन विशिष्ट कोड का उपयोग करते हुए , अक्सर कुछ सिस्टम लाइब्रेरी में)। आम तौर पर उस संचार को सिस्टम कॉल के माध्यम से किया जाता है । लिनक्स कर्नेल पर उपलब्ध सिस्टम कॉल की सूची के लिए syscalls (2) में उदाहरण के लिए देखें ।

देखने के अनुप्रयोग बिंदु से, एक syscall एक प्राथमिक मशीन निर्देश है जैसे SYSENTERx86-64 पर कुछ सम्मेलनों ( ABB ) के साथ

मेरे लिनक्स डेस्कटॉप पर, Q11 लाइब्रेरीज़ X11 सर्वर Xorg थ्रू X विंडोज प्रोटोकॉल के साथ संचार करने वाले X11 क्लाइंट लाइब्रेरीज़ से ऊपर हैं ।

लिनक्स पर, lddपुस्तकालयों पर निर्भरता की (लंबी) सूची देखने के लिए अपने निष्पादन योग्य पर उपयोग करें। pmapरनिंग प्रक्रिया का उपयोग यह देखने के लिए करें कि कौन से रनटाइम में "लोड" हैं। लिनक्स पर बीटीडब्ल्यू, आपका एप्लिकेशन शायद केवल मुफ्त सॉफ्टवेयर का उपयोग कर रहा है, आप इसके स्रोत कोड (क्यूटी से, एक्सलिब, एफबीआईसी, ... कर्नेल) का अध्ययन कर सकते हैं और अधिक समझ सकते हैं कि क्या हो रहा है।


2
संदर्भ के लिए, एएनएसआई यूएस $ 60 की थोड़ी कम अपमानजनक कीमत के लिए सी ++ 11 कल्पना बेचता है । (यह आधा हुआ करता था, लेकिन मुद्रास्फीति ।: पी) इसे INCITS / ISO / IEC 14882 के रूप में लेबल किया गया है, लेकिन यह कम से कम एक ही आधार कल्पना ISO ऑफ़र है। इरेटा / टीआर के बारे में निश्चित नहीं है।
cHao

19

मुझे लगता है कि आप जो अवधारणा याद कर रहे हैं वह सिस्टम कॉल है । प्रत्येक ऑपरेटिंग सिस्टम संसाधनों और कार्यक्षमता की एक विशाल मात्रा प्रदान करता है जिसे आप निम्न-स्तरीय ऑपरेटिंग सिस्टम से संबंधित चीजों को करने के लिए टैप कर सकते हैं। यहां तक ​​कि जब आप एक नियमित लाइब्रेरी फ़ंक्शन कहते हैं, तो यह संभवतः पर्दे के पीछे एक सिस्टम कॉल कर रहा है।

सिस्टम कॉल ऑपरेटिंग सिस्टम की शक्ति का उपयोग करने का एक निम्न-स्तरीय तरीका है, लेकिन उपयोग करने के लिए जटिल और बोझिल हो सकता है, इसलिए अक्सर एपीआई में "लिपटे" होते हैं ताकि आपको सीधे उनसे निपटना न पड़े। लेकिन नीचे, आप जो कुछ भी करते हैं, उसमें ओ / एस से संबंधित संसाधन शामिल हैं, सिस्टम कॉल का उपयोग करेंगे, जिसमें प्रिंटिंग, नेटवर्किंग और सॉकेट आदि शामिल हैं।

विंडोज़ के मामले में, माइक्रोसॉफ्ट विंडोज का जीयूआई वास्तव में कर्नेल में लिखा गया है, इसलिए विंडोज़, पेंटिंग ग्राफिक्स आदि बनाने के लिए सिस्टम कॉल हैं। अन्य ऑपरेटिंग सिस्टमों में, जीयूआई कर्नेल का हिस्सा नहीं हो सकता है, जिस स्थिति में जहां तक ​​मुझे पता है कि GUI से संबंधित चीजों के लिए कोई सिस्टम कॉल नहीं होगा, और आप जो भी निम्न-स्तरीय ग्राफिक्स और इनपुट संबंधित कॉल उपलब्ध हैं, उससे भी कम स्तर पर काम कर सकते हैं।


3
महत्वपूर्ण बात जो याद आ रही है वह यह है कि सिस्टम कॉल किसी भी तरह से जादू नहीं है। वे कर्नेल द्वारा सेवित होते हैं जो आमतौर पर C (++) में लिखा जाता है। इसके अलावा, syscalls भी आवश्यक नहीं हैं। मेमोरी सुरक्षा के बिना अल्पविकसित ओएस में, विंडोज़ को सीधे हार्डवेयर फ्रेमबफ़र में पिक्सेल डालकर खींचा जा सकता है।
el.pescado

15

अच्छा प्रश्न। हर नए C या C ++ डेवलपर के दिमाग में यह होता है। मैं इस पोस्ट के बाकी हिस्सों के लिए एक मानक x86 मशीन मान रहा हूं। यदि आप Microsoft C ++ कंपाइलर का उपयोग कर रहे हैं, तो अपना नोटपैड खोलें और इसे टाइप करें (फ़ाइल Test.c नाम दें)

int main(int argc, char **argv)
{
   return 0
}

और अब इस फ़ाइल (डेवलपर कमांड प्रॉम्प्ट का उपयोग करके) cl Test.c /FaTest.asm को संकलित करें

अब अपने नोटपैड में Test.asm खोलें। आप जो देखते हैं वह अनुवादित कोड है - C / C ++ का असेंबलर में अनुवाद किया जाता है। क्या आपको संकेत मिलता है?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C / C ++ प्रोग्राम को धातु पर चलाने के लिए डिज़ाइन किया गया है। जिसका अर्थ है कि उनके पास निचले स्तर के हार्डवेयर तक पहुंच है जो हार्डवेयर की क्षमताओं का दोहन करना आसान बनाता है। कहो, मैं एक x86 मशीन पर सी लाइब्रेरी गेटेक () लिखने जा रहा हूं।

कोडांतरक के आधार पर मैं कुछ इस तरह लिखूंगा:

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

मैं इसे एक असेंबलर के साथ चलाता हूं और एक .OBJ जेनरेट करता हूं - इसे getch.obj नाम दें।

मैं तब एक सी प्रोग्राम लिखता हूं (मैं कुछ भी नहीं जानता)

extern char getch();

void main(int, char **)
{
  getch();
}

अब इस फाइल को नाम दें - GetChTest.c। Getch.obj पास करके इस फ़ाइल को संकलित करें। (या .obj और लिंक GetChTest.Obj और getch.Obj के लिए व्यक्तिगत रूप से संकलन करें GetChTest.exe का उत्पादन करने के लिए)।

GetChTest.exe चलाएं और आप पाएंगे कि यह कीबोर्ड इनपुट की प्रतीक्षा कर रहा है।

C / C ++ प्रोग्रामिंग सिर्फ भाषा के बारे में नहीं है। एक अच्छा C / C ++ प्रोग्रामर होने के लिए आपको मशीन के प्रकार पर अच्छी समझ होनी चाहिए जो इसे चलाता है। आपको यह जानना होगा कि स्मृति प्रबंधन कैसे संभाला जाता है, रजिस्टर कैसे संरचित किए जाते हैं, आदि, आपको नियमित प्रोग्रामिंग के लिए इन सभी जानकारी की आवश्यकता नहीं हो सकती है - लेकिन वे आपकी बहुत मदद करेंगे। बुनियादी हार्डवेयर ज्ञान के अलावा, यह निश्चित रूप से मदद करता है यदि आप समझते हैं कि कंपाइलर कैसे काम करता है (यानी, यह कैसे अनुवाद करता है) - जो आपको आवश्यक के रूप में अपना कोड ट्विस्ट करने में सक्षम कर सकता है। यह एक दिलचस्प पैकेज है!

दोनों भाषाएं __asm ​​कीवर्ड का समर्थन करती हैं जिसका अर्थ है कि आप अपनी विधानसभा भाषा कोड भी मिला सकते हैं। C और C ++ सीखना आपको समग्र रूप से एक बेहतर गोल प्रोग्रामर बना देगा।

यह हमेशा असेंबलर के साथ लिंक करने के लिए आवश्यक नहीं है। मैंने इसका उल्लेख किया था क्योंकि मुझे लगा कि इससे आपको बेहतर समझने में मदद मिलेगी। अधिकतर, ऐसी अधिकांश लाइब्रेरी कॉल ऑपरेटिंग सिस्टम द्वारा प्रदान किए गए सिस्टम कॉल / एपीआई का उपयोग करते हैं (बदले में ओएस हार्डवेयर इंटरैक्शन सामान करता है)।


10

C ++ ... अचानक C ++ में लिखी गई लाइब्रेरी के माध्यम से अचानक ऐसी क्षमताएं कैसे प्राप्त होती हैं?

अन्य पुस्तकालयों का उपयोग करने के बारे में कुछ भी जादुई नहीं है। पुस्तकालय कार्यों के सरल बड़े बैग हैं जिन्हें आप कॉल कर सकते हैं।

अपने आप को इस तरह एक समारोह लिखने पर विचार करें

void addExclamation(std::string &str)
{
    str.push_back('!');
}

अब अगर आप उस फाइल को शामिल करते हैं तो आप लिख सकते हैं addExclamation(myVeryOwnString);। अब आप पूछ सकते हैं कि, "C ++ में अचानक विस्मय बोधक बिंदुओं को एक तार से जोड़ने की क्षमता कैसे प्राप्त हुई?" उत्तर आसान है: आपने ऐसा करने के लिए एक फ़ंक्शन लिखा था, फिर आपने इसे कॉल किया।

तो आपके सवाल का जवाब देने के लिए कि C ++ में लिखी गई लाइब्रेरियों के माध्यम से सी + + कैसे विंडोज़ खींचने की क्षमता प्राप्त कर सकती है, इसका उत्तर समान है। किसी और ने ऐसा करने के लिए फ़ंक्शन लिखा है, और फिर उन्हें संकलित किया और उन्हें पुस्तकालय के रूप में आपको दिया।

अन्य प्रश्न उत्तर देते हैं कि विंडो ड्राइंग वास्तव में कैसे काम करती है, लेकिन आपने भ्रमित किया कि लाइब्रेरी कैसे काम करती है इसलिए मैं आपके प्रश्न के सबसे बुनियादी हिस्से को संबोधित करना चाहता था।


8

कुंजी एक एपीआई को उजागर करने के लिए ऑपरेटिंग सिस्टम की संभावना है और इस एपीआई का उपयोग कैसे किया जाए, इस पर एक विस्तृत विवरण।

ऑपरेटिंग सिस्टम कॉलिंग कन्वेंशन के साथ एपीआई का एक सेट प्रदान करता है। कॉलिंग कन्वेंशन एक पैरामीटर को एपीआई में दिए जाने के तरीके को परिभाषित कर रहा है और परिणाम कैसे लौटाए जाते हैं और वास्तविक कॉल को कैसे निष्पादित किया जाता है।

ऑपरेटिंग सिस्टम और उनके लिए कोड बनाने वाले कंपाइलर एक साथ अच्छी तरह से खेलते हैं, इसलिए आपको आमतौर पर इसके बारे में सोचने की ज़रूरत नहीं है, बस इसका उपयोग करें।


7

विंडो बनाने के लिए किसी विशेष सिंटैक्स की आवश्यकता नहीं है। यह आवश्यक है कि ओएस विंडोज़ बनाने के लिए एक एपीआई प्रदान करता है। इस तरह के एपीआई में साधारण फ़ंक्शन कॉल होते हैं जिसके लिए C ++ सिंटैक्स प्रदान करता है।

इसके अलावा C और C ++ को सिस्टम प्रोग्रामिंग लैंग्वेज कहा जाता है और मनमाने ढंग से पॉइंटर्स (जो हार्डवेयर द्वारा किसी डिवाइस पर मैप किए जा सकते हैं) तक पहुंचने में सक्षम हैं। इसके अतिरिक्त, यह असेंबली में परिभाषित फ़ंक्शन को कॉल करने के लिए भी काफी सरल है, जो प्रोसेसर को प्रदान करने वाले कार्यों की पूरी श्रृंखला की अनुमति देता है। इसलिए सी या सी ++ और असेंबली की एक छोटी राशि का उपयोग करके स्वयं एक ओएस लिखना संभव है।

यह भी उल्लेख किया जाना चाहिए कि क्यूटी एक बुरा उदाहरण है, क्योंकि यह सी ++ 'सिंटैक्स का विस्तार करने के लिए एक तथाकथित मेटा कंपाइलर का उपयोग करता है । हालांकि यह वास्तव में विंडोज़ को आकर्षित करने या बनाने के लिए ओएस द्वारा प्रदान किए गए एपीआई में कॉल करने की क्षमता से संबंधित नहीं है।


7

पहले, थोड़ा गलतफहमी है, मुझे लगता है

C ++ कैसे करता है, जो पहले कोई सिंटैक्स नहीं था जो ओएस को खिड़की या नेटवर्क के माध्यम से संवाद करने के लिए पूछने में सक्षम था

ओएस संचालन करने के लिए कोई सिंटैक्स नहीं है । यह शब्दार्थ का प्रश्न है ।

सी ++ में लिखी गई पुस्तकालयों के माध्यम से अचानक ऐसी क्षमताएं प्राप्त होती हैं

खैर, ऑपरेटिंग सिस्टम ज्यादातर सी में रिटेन होता है। आप बाहरी कोड को कॉल करने के लिए साझा लाइब्रेरी (इसलिए, dll) का उपयोग कर सकते हैं । इसके अतिरिक्त, ऑपरेटिंग सिस्टम कोड syscalls * पर सिस्टम रूटीन को पंजीकृत कर सकता है या बाधित कर सकता है जिसे आप असेंबली का उपयोग करके कॉल कर सकते हैं । वह साझा लाइब्रेरी अक्सर आपके लिए केवल सिस्टम कॉल करती है, इसलिए आपको इनलाइन असेंबली का उपयोग करने से बख्शा जाता है।

यहाँ उस पर अच्छा ट्यूटोरियल है: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
यह लिनक्स के लिए है, लेकिन सिद्धांत समान हैं।

ऑपरेटिंग सिस्टम ग्राफिक कार्ड, नेटवर्क कार्ड आदि पर संचालन कैसे कर रहा है? यह एक बहुत व्यापक विषय है, लेकिन ज्यादातर आपको इंटरप्ट, पोर्ट तक पहुंचने या विशेष मेमोरी क्षेत्र में कुछ डेटा लिखने की आवश्यकता है। चूंकि ऑपरेशन सुरक्षित हैं, इसलिए आपको उन्हें वैसे भी ऑपरेटिंग सिस्टम के माध्यम से कॉल करने की आवश्यकता है।


7

अन्य उत्तरों को थोड़ा अलग दृश्य प्रदान करने के प्रयास में, मैं इस तरह का उत्तर दूंगा।

(अस्वीकरण: मैं चीजों को थोड़ा सरल कर रहा हूं, जो स्थिति मैं देता हूं वह विशुद्ध रूप से काल्पनिक है और जीवन के लिए 100% सच होने के बजाय अवधारणाओं को प्रदर्शित करने के साधन के रूप में लिखा गया है)।

दूसरे दृष्टिकोण से चीजों के बारे में सोचें, कल्पना करें कि आपने मूल थ्रेडिंग, विंडोिंग और मेमोरी प्रबंधन क्षमताओं के साथ एक सरल ऑपरेटिंग सिस्टम लिखा है। आप C ++ लाइब्रेरी को यूजर्स को C ++ में प्रोग्राम करने देने के लिए लागू करना चाहते हैं और विंडो बनाना, विंडोज पर ड्रॉ करना आदि जैसे काम करते हैं। सवाल यह है कि यह कैसे किया जाए।

सबसे पहले, चूंकि C ++ मशीन कोड के लिए संकलित है, इसलिए आपको C ++ के साथ इंटरफ़ेस करने के लिए मशीन कोड का उपयोग करने का एक तरीका परिभाषित करना होगा। यह वह जगह है जहां फ़ंक्शन आते हैं, फ़ंक्शन तर्कों को स्वीकार करते हैं और रिटर्न मान देते हैं, इस प्रकार वे कोड के विभिन्न वर्गों के बीच डेटा स्थानांतरित करने का एक मानक तरीका प्रदान करते हैं। वे एक कॉलिंग कन्वेंशन के रूप में जाना जाने वाला कुछ स्थापित करके ऐसा करते हैं ।

एक कॉलिंग कन्वेंशन में कहा गया है कि कहां और कैसे तर्कों को स्मृति में रखा जाना चाहिए ताकि एक फ़ंक्शन उन्हें तब मिल सके जब इसे निष्पादित किया जाए। जब किसी फ़ंक्शन को कॉल किया जाता है, तो कॉलिंग फ़ंक्शन मेमोरी में तर्कों को रखता है और फिर सीपीयू को दूसरे फ़ंक्शन पर कूदने के लिए कहता है, जहां वह वापस जाने से पहले यह करता है कि यह कहाँ से बुलाया गया था। इसका मतलब यह है कि कोड कहा जा रहा है बिल्कुल कुछ भी हो सकता है और यह नहीं बदलेगा कि फ़ंक्शन कैसे कहा जाता है। हालांकि इस मामले में, फ़ंक्शन के पीछे का कोड ऑपरेटिंग सिस्टम के लिए प्रासंगिक होगा और ऑपरेटिंग सिस्टम की आंतरिक स्थिति पर काम करेगा।

इसलिए, कई महीनों बाद और आपको अपने सभी OS फ़ंक्शंस मिल गए हैं। आपके उपयोगकर्ता विंडो बनाने और उन पर आकर्षित करने के लिए फ़ंक्शन कॉल कर सकते हैं, वे थ्रेड और सभी प्रकार की अद्भुत चीजें बना सकते हैं। यहाँ समस्या यह है कि, आपके OS के फ़ंक्शंस लिनक्स के फ़ंक्शंस या विंडोज के फ़ंक्शंस से भिन्न होने जा रहे हैं। तो आप तय करते हैं कि आपको उपयोगकर्ता को एक मानक इंटरफ़ेस देने की आवश्यकता है ताकि वे पोर्टेबल कोड लिख सकें। यहीं क्यूटी अंदर आता है।

जैसा कि आप लगभग निश्चित रूप से जानते हैं, क्यूटी के पास उपयोगी वर्गों और कार्यों का भार है जो ऑपरेटिंग सिस्टम करते हैं, लेकिन एक तरह से अंतर्निहित ऑपरेटिंग सिस्टम से स्वतंत्र दिखाई देते हैं। जिस तरह से यह काम करता है वह यह है कि क्यूटी कक्षा और फ़ंक्शंस प्रदान करता है जो उपयोगकर्ता को दिखाई देने के तरीके में समान हैं, लेकिन फ़ंक्शंस के पीछे का कोड प्रत्येक ऑपरेटिंग सिस्टम के लिए अलग है। उदाहरण के लिए क्यूटी का QApplication :: closeAllWindows () वास्तव में उपयोग किए गए संस्करण के आधार पर प्रत्येक ऑपरेटिंग सिस्टम के विशेष विंडो समापन फ़ंक्शन को कॉल करेगा। विंडोज में यह सबसे अधिक संभावना है कि CloseWindow (hwnd) को कॉल करेगा, जबकि X विंडो सिस्टम का उपयोग करते हुए ओएस पर, यह संभवतः XDestroyWindow (डिस्प्ले, विंडो) को कॉल करेगा।

जैसा कि स्पष्ट है, एक ऑपरेटिंग सिस्टम में कई परतें होती हैं, जिनमें से सभी को कई किस्मों के इंटरफेस के माध्यम से इंटरैक्ट करना पड़ता है। ऐसे कई पहलू हैं जिन पर मैंने हाथ भी नहीं लगाया है, लेकिन उन सभी को समझाने में बहुत लंबा समय लगेगा। यदि आप ऑपरेटिंग सिस्टम के आंतरिक कामकाज में आगे रुचि रखते हैं, तो मैं ओएस देव विकी की जांच करने की सलाह देता हूं ।

हालांकि, यह ध्यान में रखें कि कई ऑपरेटिंग सिस्टम C / C ++ में इंटरफेस का खुलासा करने का कारण यह है कि वे मशीन कोड के लिए संकलित हैं, वे विधानसभा निर्देशों को अपने कोड के साथ मिश्रित करने की अनुमति देते हैं और वे प्रोग्रामर को एक महान डिग्री प्रदान करते हैं।

फिर, यहाँ बहुत कुछ चल रहा है। मैं यह बताना चाहता हूं कि पुस्तकालयों की तरह कैसे .so और .dll फ़ाइलों को C / C ++ में नहीं लिखा जाना चाहिए और इसे असेंबली या अन्य भाषाओं में लिखा जा सकता है, लेकिन मुझे लगता है कि अगर मैं और जोड़ूं तो मुझे भी पसंद आएगा एक पूरा लेख लिखें, और जितना मुझे करना अच्छा लगेगा कि मेरे पास इसे होस्ट करने के लिए कोई साइट नहीं है।


6

जब आप स्क्रीन पर कुछ खींचने की कोशिश करते हैं, तो आपका कोड कुछ अन्य कोड को कॉल करता है, जो किसी अन्य कोड (आदि) को कॉल करता है, अंत में एक "सिस्टम कॉल" होता है, जो एक विशेष निर्देश है जो सीपीयू निष्पादित कर सकता है। इन निर्देशों को या तो असेंबली में लिखा जा सकता है या C ++ में लिखा जा सकता है यदि कंपाइलर उनके "इंट्रिंसिक्स" का समर्थन करता है (जो कि फ़ंक्शन हैं जो कंपाइलर "विशेष रूप से" को विशेष कोड में परिवर्तित करके संभालता है जिसे सीपीयू समझ सकता है)। उनका काम ऑपरेटिंग सिस्टम को कुछ करने के लिए कहना है।

जब सिस्टम कॉल होता है, तो एक फ़ंक्शन को कॉल किया जाता है जो दूसरे फ़ंक्शन (आदि) को कॉल करता है जब तक कि डिस्प्ले ड्राइवर को स्क्रीन पर कुछ खींचने के लिए नहीं कहा जाता है। उस बिंदु पर, डिस्प्ले ड्राइवर एक विशेष क्षेत्र को भौतिक मेमोरी में देखता है जो वास्तव में मेमोरी नहीं है, बल्कि एक एड्रेस रेंज है जिसे लिखा जा सकता है जैसे कि यह मेमोरी थी। इसके बजाय, हालांकि, उस एड्रेस रेंज में लिखने से ग्राफिक्स हार्डवेयर मेमोरी मेमोरी को इंटरसेप्ट करता है, और स्क्रीन पर कुछ आकर्षित करता है।
मेमोरी के इस क्षेत्र में लिखना कुछ ऐसा है जिसे C ++ में कोडित किया जा सकता है, क्योंकि सॉफ्टवेयर की तरफ यह सिर्फ एक नियमित मेमोरी एक्सेस है। यह सिर्फ इतना है कि हार्डवेयर इसे अलग तरीके से संभालता है।
तो यह वास्तव में एक बुनियादी व्याख्या है कि यह कैसे काम कर सकता है।


4
Afaik एक systemcall वास्तव में एक cpu निर्देश नहीं है, और आंतरिक रूप से इसका कोई लेना-देना नहीं है। यह ऑपरेटिंग सिस्टम कर्नेल का अधिक कार्य है, जो उपकरणों के साथ संचार करता है।
MatthiasB

3
@ मैथियासबी: ठीक है, आप गलत हैं, क्योंकि syscall(और इसका चचेरा भाई sysenter) वास्तव में एक सीपीयू निर्देश है।
user541686

2
यह केवल आपके उत्तर को बेहतर बनाने के लिए एक संकेत था, क्योंकि यह खुद के लिए स्पष्ट नहीं था। इसे व्यक्तिगत हमले या किसी भी चीज के रूप में न देखें।
MatthiasB

1
@ मैथियासबी: मैं इसे व्यक्तिगत रूप से नहीं ले रहा हूं। मैं कह रहा हूं कि मुझे पहले से ही पता है कि उत्तर तथ्यात्मक रूप से 100% सटीक नहीं है, लेकिन मुझे लगता है कि यह ओपी को जवाब देने के लिए एक अच्छा पर्याप्त सरलीकरण है - इसलिए, यदि आप वास्तव में एक बेहतर उत्तर लिखने के तरीके के बारे में जानते हैं, तो कृपया अपना खुद का लिखें उत्तर दें या मेरा संपादन करने के लिए समय निकालें। मेरे पास वास्तव में ऐसा कुछ भी नहीं है जो मुझे लगता है कि इसके लायक है, इसलिए यदि आप इस पृष्ठ पर कुछ बेहतर देखना चाहते हैं तो आपको प्रयास में खुद को लगाना होगा।
user541686

3
सॉफ्टवेयर इंटरप्ट का उपयोग करके सिस्टम कॉल किया जाता है। जैसे निर्देश sysenterअनुकूलित कॉल पथ हैं, क्योंकि बाधा हैंडलर द्वारा उपयोग किए जा रहे संदर्भ स्विचिंग हर किसी के रूप में तेजी से वांछित नहीं था, लेकिन मूल रूप से यह अभी भी एक सॉफ्टवेयर जनित बाधा है, जबकि ओएस कर्नेल द्वारा स्थापित हैंडलर को वेक्टरिंग द्वारा नियंत्रित किया जाता है। IS द्वारा sysenterकी गई संदर्भ स्विचिंग प्रक्रिया का एक भाग रिंग 0 को सेट करने के लिए प्रोसेसर में मोड बिट्स को बदल रहा है - सभी विशेषाधिकार प्राप्त निर्देशों, रजिस्टरों और मेमोरी और I / O क्षेत्रों तक पूर्ण पहुंच।
बेन वोइग्ट

4

आपका C ++ प्रोग्राम Qt लाइब्रेरी (C ++ में भी कोडित) का उपयोग कर रहा है। Qt लाइब्रेरी Windows CreateWindowEx फ़ंक्शन का उपयोग कर रही होगी (जो कि कर्नेल 32.dll के अंदर C कोड की गई थी)। या लिनक्स के तहत यह एक्सलिब (सी में भी कोडित) का उपयोग किया जा सकता है , लेकिन यह कच्चे बाइट्स भी भेज सकता है कि एक्स प्रोटोकॉल में इसका मतलब है " कृपया मेरे लिए एक विंडो बनाएं "।

आपके कैच -२२ प्रश्न से संबंधित ऐतिहासिक नोट है कि "पहला C ++ कंपाइलर C ++ में लिखा गया था", हालाँकि वास्तव में यह कुछ C ++ धारणाओं वाला C कंपाइलर था, पर्याप्त था इसलिए यह पहले वर्जन को संकलित कर सकता था, जो तब स्वयं कंपाइल कर सकता था। ।

इसी तरह, जीसीसी कंपाइलर जीसीसी एक्सटेंशन का उपयोग करता है: इसे पहले एक संस्करण में संकलित किया जाता है, फिर खुद को फिर से जोड़ने के लिए उपयोग किया जाता है। (जीसीसी निर्माण निर्देश)


2

मैं इस प्रश्न को कैसे देखता हूं यह वास्तव में एक संकलक प्रश्न है।

इसे इस तरह से देखें, आप असेंबली में कोड का एक टुकड़ा लिखते हैं (आप इसे किसी भी भाषा में कर सकते हैं) जो आपकी नई लिखित भाषा का अनुवाद करता है जिसे आप Z ++ को असेंबली में कॉल करना चाहते हैं, सरलता के लिए इसे कंपाइलर कहते हैं (यह एक संकलक है) ।

अब आप इस कंपाइलर को कुछ बुनियादी कार्य देते हैं, ताकि आप int, string, arrays आदि लिख सकें। वास्तव में आप इसे पर्याप्त क्षमता देते हैं ताकि आप कंपाइलर को Z ++ में ही लिख सकें। और अब आपके पास Z ++ में लिखा गया Z ++ का कंपाइलर है, बहुत साफ-सुथरा सही।

Whats भी कूलर है कि अब आप पहले से मौजूद क्षमताओं का उपयोग करके उस कंपाइलर में क्षमताओं को जोड़ सकते हैं, इस प्रकार पिछली विशेषताओं का उपयोग करके नई सुविधाओं के साथ Z ++ भाषा का विस्तार कर सकते हैं

एक उदाहरण, यदि आप किसी भी रंग में पिक्सेल खींचने के लिए पर्याप्त कोड लिखते हैं, तो आप Z ++ का उपयोग करके अपनी इच्छानुसार कुछ भी आकर्षित करने के लिए इसका विस्तार कर सकते हैं।


0

हार्डवेयर वह है जो इसे होने देता है। आप ग्राफिक्स मेमोरी को एक बड़े एरे (स्क्रीन पर हर पिक्सेल से मिलकर) के रूप में सोच सकते हैं। स्क्रीन पर आरेखित करने के लिए आप इस मेमोरी को C ++ या किसी भी भाषा का उपयोग करके लिख सकते हैं जो उस मेमोरी तक सीधी पहुँच की अनुमति देता है। वह मेमोरी सिर्फ ग्राफिक्स कार्ड के द्वारा या स्थित होने के लिए होती है।

आधुनिक सिस्टम पर ग्राफिक्स मेमोरी को सीधे एक्सेस करने के लिए आपको विभिन्न प्रतिबंधों के कारण ड्राइवर लिखने की आवश्यकता होगी ताकि आप अप्रत्यक्ष साधनों का उपयोग करें। पुस्तकालय जो एक विंडो बनाते हैं (वास्तव में किसी भी अन्य छवि की तरह एक छवि) और फिर उस छवि को ग्राफिक्स मेमोरी में लिखें जिसे जीपीयू फिर स्क्रीन पर प्रदर्शित करता है। विशिष्ट मेमोरी लोकेशन पर लिखने की क्षमता को छोड़कर भाषा में कुछ भी नहीं जोड़ा जाना चाहिए, जो कि पॉइंटर्स के लिए है।


मैं जिस बिंदु को बनाने की कोशिश कर रहा था, वह यह है कि किसी भाषा को इस अर्थ में "विस्तार" करने की आवश्यकता नहीं है कि भाषा के एक नए संस्करण को फिर से लिखने की आवश्यकता है, और यह वास्तव में परिपत्र नहीं है क्योंकि कुछ भी दिलचस्प कार्यक्रम करना है हार्डवेयर के साथ इंटरफ़ेस करना चाहिए।
जॉन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.