x86-64 मशीन कोड, 8 बाइट्स
ब्रूस फोर्ट के समाधान से प्रेरित है , लेकिन थोड़ा सा बराबर है। :-)
8D 07 lea eax, [rdi] ; put copy of input parameter in EAX
D1 EF shr edi, 1 ; shift LSB into CF
InfiniteLoop:
F3 73 FD rep jnc InfiniteLoop ; test CF; infinite loop back here if input was even
C3 ret ; return with original input in EAX if it was odd
एक एकल पूर्णांक पैरामीटर EDIरजिस्टर में लिया जाता है , सिस्टम V AMD64 कॉलिंग कन्वेंशन के बाद।
इस मूल्य की एक प्रति शुरू में बनाई गई है, और इसे डाल दिया गया है, EAXयदि उपयुक्त हो तो इसे वापस किया जा सकता है। ( LEAसामान्य के बजाय इसका उपयोग किया जाता है MOVक्योंकि हमें विषम बाइट्स के साथ एक निर्देश की आवश्यकता होती है।)
फिर, मान को EDI1 से दाईं ओर स्थानांतरित कर दिया जाता है, जो स्थानांतरित किए गए बिट को कैरी फ़्लैग (CF) में रखता है। यह बिट 0 होगा यदि संख्या समान थी, या 1 यदि यह विषम था।
हम फिर JNCनिर्देश का उपयोग करते हुए सीएफ का परीक्षण करते हैं , जो केवल तभी सीएफ होगा यदि सीएफ 0 है (यानी, संख्या सम थी)। इसका मतलब यह है कि हम मूल्यों के लिए एक अनंत लूप में जाएंगे। विषम मानों के लिए, हम गिर जाते हैं और मूल मूल्य (में EAX) वापस आ जाता है।
JNCनिर्देश के साथ एक चाल है , हालांकि, यह एक REPउपसर्ग है! आम तौर पर, REPउपसर्गों का उपयोग केवल कड़े निर्देशों के साथ किया जाता है, लेकिन क्योंकि इंटेल और एएमडी मैनुअल दोनों सहमत हैं कि अप्रासंगिक / अतिरेक / अतिरेक REPउपसर्गों को अनदेखा किया जाता है, हम इसे 3 बायपास बनाने के लिए शाखा निर्देश पर फेंक देते हैं। इस तरह, जम्प निर्देश में एन्कोडेड हो जाने वाली सापेक्ष ऑफ़सेट भी विषम है। (और, ज़ाहिर है, REPअपने आप में एक अजीब-बाइट उपसर्ग है।)
धन्यवाद अच्छाई RETएक विषम बाइट का उपयोग करके एन्कोडेड है!
इसे ऑनलाइन आज़माएं!
यदि आप यह मानकर नहीं लौटते हैं कि यदि यह विषम है या अनंत लूप में जा रहा है तो यह भी (ताकि आप कभी न लौटें) चुनौती की "आउटपुट" आवश्यकताओं को पूरा करता है, या आप कुछ और अधिक दिलचस्प चाहते हैं, यहाँ एक फ़ंक्शन है यह एक सीरियल पोर्ट के लिए मूल्य को आउटपुट करता है (लेकिन केवल अगर यह विषम है, तो निश्चित रूप से)।
x86-64 मशीन कोड (सीरियल पोर्ट के लिए आउटपुट), 17 बाइट्स
8D 07 lea eax, [rdi] ; put copy of input parameter (EDI) in EAX
B1 F7 mov cl, 0xf7 ; put 0xF7 into low-order bits of CX
B5 03 mov ch, 0x03 ; put 0x03 into high-order bits of CX
FE C1 inc cl ; increment low-order bits of CX to 0xF8 (so all together it's now 0x3F8)
0F B7 D1 movzx edx, cx ; move CX to DX ("MOV DX, CX" would have a 16-bit prefix of 0x66)
D1 EF shr edi, 1 ; shift LSB of input parameter into CF
73 01 jnc IsEven ; test CF: branch if 0 (even), fall through if 1 (odd)
EF out dx, eax ; output EAX (original input) to I/O port 0x3F8 (in DX)
IsEven:
C3 ret ; return
यह थोड़ा और दिलचस्प बनाता है कि कोड अधिक करता है , जिसका अर्थ है कि यह उन सभी निर्देशों का उपयोग करना अधिक चुनौतीपूर्ण था जो केवल विषम बाइट्स का उपयोग करके एन्कोड किए गए हैं। बेशक, इसका मतलब यह भी है कि यह कोड गोल्फ में विफल रहता है, इसलिए यह एक तरह का ट्रेडऑफ है - क्या आप दिलचस्प और चुनौतीपूर्ण चाहते हैं, या क्या आप कम चाहते हैं?
वैसे भी, यह I / O पोर्ट 0x3F8 को लिखने के लिए x86 OUTनिर्देश का उपयोग करता है , जो कि पीसी पर मानक COM1 सीरियल पोर्ट है । मज़ेदार हिस्सा, निश्चित रूप से, यह है कि सभी मानक I / O पोर्ट (धारावाहिक और समानांतर) के पते भी हैं, इसलिए उन्हें केवल OUTनिर्देश के लिए तुरंत इनकोड नहीं किया जा सकता है या सीधे रजिस्टर में ले जाया जा सकता है। आपको वास्तविक मूल्य से कम के साथ आरंभ करना होगा, और फिर रजिस्टर में मूल्य बढ़ाना होगा। आप हेरफेर के लिए कुछ रजिस्टरों का उपयोग करने के लिए भी सीमित हैं क्योंकि आपको उन रजिस्टरों की आवश्यकता है जो ऑपरेंड्स के उपयोग के दौरान निर्देश में अजीब बाइट्स का उपयोग करके एन्कोडेड हैं।
इसके अलावा, मुझे लूप के शीर्ष पर DXरजिस्टर (रजिस्टर के माध्यम से CX) को इनिशियलाइज़ करना था , भले ही यह केवल तभी आवश्यक हो जब मान विषम हो, यह सुनिश्चित करने के लिए कि JNCनिर्देश में एक विषम ऑफसेट होगा। हालाँकि, हम जिस चीज को छोड़ रहे हैं वह OUTनिर्देश है, यह सब कोड बेकार साइकिल और क्लोबर स्क्रैच रजिस्टर है; यह वास्तव में कुछ भी उत्पादन नहीं करता है , इसलिए यह नियमों को नहीं तोड़ता है।
अंत में, यह फ़ंक्शन इनपुट वैल्यू के साथ वापस आ जाएगा (या तो काम किया है या सीरियल पोर्ट पर आउटपुट नहीं किया है) EAX। लेकिन यह वास्तव में किसी भी नियम को नहीं तोड़ता है; असेंबली लैंग्वेज के सभी फंक्शन एक मान के साथ लौटेंगे EAX— सवाल यह है कि क्या यह महत्वपूर्ण मूल्य या कचरा मूल्य है। यह फ़ंक्शन के प्रलेखन द्वारा निर्धारित किया जाता है (अनिवार्य रूप से, क्या यह एक मान लौटाता है या क्या यह वापस लौटता है void), और इस मामले में, मैं इसे एक मान नहीं लौटाने के रूप में दस्तावेज कर रहा हूं। :-)
इसके लिए कोई TIO लिंक नहीं, क्योंकि यह सीरियल पोर्ट पर आउटपुट लागू नहीं करता है। आपको असली लोहा, या एक कल्पना की आवश्यकता होगी।