2013-01-07 37 views
12

int32 को 64-बिट native int पर जोड़ते समय, क्या सीएलआर साइन-विस्तार या शून्य-32-बिट पूर्णांक का विस्तार करता है? और सबसे महत्वपूर्ण बात यह है कि यह किस विकल्प पर आधारित है?एक 64-बिट देशी int में int32 जोड़ने का परिणाम?


मैं एक .NET संकलक लिख रहा हूँ और ECMA विनिर्देश तरह से पढ़ा है, लेकिन एक जवाब नहीं मिल सका। int32, int64, और native int:

CLI मूल्यांकन के ढेर पर संग्रहीत मूल्यों पर अपने अभियान में इन प्रकार के केवल एक सबसेट का समर्थन करता है।
- ECMA 335, खंड- I 12.1: समर्थित डेटा प्रकार

मूल्यांकन स्टैक पर मूल्यों के बाद से उनके signedness पर कोई जानकारी नहीं है, जिसके लिए निर्देश ऑपरेंड के signedness बात दो प्रकार हैं: के लिए एक हस्ताक्षरित और एक हस्ताक्षरित पूर्णांक के लिए एक। add, sub और mul निर्देश (जो ओवरफ़्लो की जांच नहीं करते हैं) ऑपरेटरों की हस्ताक्षर की परवाह करने की आवश्यकता नहीं है जब तक कि ऑपरेंड एक ही आकार के होते हैं, और इसलिए केवल एक ही संस्करण होता है। हालांकि, ऑपरेंड हमेशा एक ही आकार नहीं कर रहे हैं ...

ECMA 335, धारा III 1.5: ओपेरैंड प्रकार तालिका कहा गया है कि एक int32 और एक native int, जोड़ा जा सकता है घटाया, गुणा और विभाजित। नतीजा फिर से native int है। 64-बिट सिस्टम पर, native int 64 बिट चौड़ा है।

ldc.i4.0   // Load int32 0 
conv.i    // Convert to (64-bit) native int 
ldc.i4.m1   // Load int32 -1 
add     // Add native int 0 and int32 0xFFFFFFFF together 

तो परिणाम क्या होगा? ध्यान दें कि, विनिर्देश के अनुसार, रनटाइम को सटीक प्रकार या स्टैक पर मानों की हस्ताक्षर को ट्रैक करने की आवश्यकता नहीं है: यह केवल int32, int64 और native int (और कुछ अन्य जो यहां प्रासंगिक नहीं हैं) को जानता है।


मैं कल्पना कर सकते हैं कि IntPtr और UIntPtr अंकगणित, क्योंकि यह आंतरिक रूप से देशी ints के रूप में प्रस्तुत किया जाता है, यह भी इसके अलावा इस तरह का प्रयोग करेंगे। हालांकि, आईएलएसपी से पता चलता है कि IntPtr और Int32 सी # में ओवरलोडेड + ऑपरेटर IntPtr क्लास पर कॉल करता है, जो केवल हस्ताक्षरित Int32 तर्क स्वीकार करता है।

इसे सीधे सीआईएल में करना (add निर्देश का उपयोग करके) यह भी इंगित करता है कि पूर्णांक को हस्ताक्षर किए जाने के रूप में व्याख्या किया जाता है। इसे मोनो में भी लागू किया जाना चाहिए था, लेकिन मुझे अपने निष्कर्षों को वापस करने के लिए कोई संदर्भ नहीं मिला।

+0

प्रचारित मूल्य के लिए चिह्न पकड़ा नहीं जाएगा। संभावित समाधानों के लिए यह जानकारी देखें (यह मैक के लिए है लेकिन इससे इस मामले में कोई फर्क नहीं पड़ता): https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/64bitPorting/MakingCode64-BitClean/MakingCode64- BitClean.html – K3N

उत्तर

5

समान बिटसाइट के दो मान जोड़ते समय हस्ताक्षर कोई फर्क नहीं पड़ता। उदाहरण के लिए, 32-बिट -10 (0xfffffff6) 32-बिट 10 (0x0000000a) में सही ढंग से 0 उत्पन्न होगा। इसके कारण, सीआईएल (सामान्य निर्देश भाषा) में केवल एक add निर्देश है।

हालांकि, अलग-अलग बिट्स के दो मान जोड़ते समय, हस्ताक्षर मामला है। उदाहरण के लिए, 32-बिट -10 से 64-बिट 10 जोड़ना 42 9 4 9 67296 (0x100000000) में हस्ताक्षर किए जाने पर, और हस्ताक्षर किए जाने पर 0 हो सकता है।

सीआईएल add अनुदेश एक देशी पूर्णांक और एक 32-बिट पूर्णांक जोड़ने की अनुमति देता है। मूल पूर्णांक 64-बिट (64-बिट सिस्टम पर) हो सकता है। परीक्षण से पता चलता है कि add 32-बिट पूर्णांक को हस्ताक्षरित पूर्णांक के रूप में मानता है, और साइन-इन करता है।This is not always correct और a bug माना जा सकता है। माइक्रोसॉफ्ट वर्तमान में इसे ठीक करने वाला नहीं है। add.ovf (हस्ताक्षरित) और add.ovf.un (अहस्ताक्षरित):

क्योंकि अतिप्रवाह जाँच करें कि क्या ऑपरेंड अहस्ताक्षरित या हस्ताक्षर किए होने के रूप में इलाज कर रहे हैं पर निर्भर करता है, वहाँ add.ovf के दो वेरिएंट हैं। हालांकि, ये वेरिएंट शून्य के सही ढंग से साइन-विस्तार भी करते हैं- एक छोटे पूर्णांक को 32-बिट पूर्णांक जोड़ते समय छोटे ऑपरेंड का विस्तार करते हैं।

तो एक देशी पूर्णांक और एक हस्ताक्षरित 32-बिट पूर्णांक जोड़ना सी # की अतिप्रवाह जांच सेटिंग के आधार पर विभिन्न परिणाम उत्पन्न कर सकता है। स्पष्ट रूप से तथ्य यह है कि मैं इसे समझ नहीं पाया सीआईएल भाषा डिजाइन में एक बग या निरीक्षण का परिणाम है।

2

आप यहां अनचाहे क्षेत्र में हैं, मुझे किसी भी .NET भाषा की जानकारी नहीं है जो वास्तव में इसकी अनुमति देता है। उनके वाक्यविन्यास परीक्षक किसी भी कोड को अस्वीकार करते हैं जो ऐसा करने का प्रयास करता है। यहां तक ​​कि दो देशी चींटियों को भी खारिज कर दिया गया है। आखिरकार यह इसके लिए मशीन कोड उत्पन्न करने के लिए जिटर पर निर्भर है। यदि आप जानना चाहते हैं कि क्या होता है तो बस प्रयोग करें। कम से कम x86 और x64 jitters का परीक्षण करना सुनिश्चित करें।

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

+0

मैंने पोस्ट में कुछ जानकारी जोड़ दी: 'Int32' को 'Int32' में जोड़ते समय सी # अधिभारित अतिरिक्त ऑपरेटर का उपयोग करता है। सीआईएल में, 'एड' निर्देश हस्ताक्षर के रूप में 'Int32' की व्याख्या करना प्रतीत होता है। हालांकि, मुझे नहीं पता क्यों। – Virtlink