x86-64 মেশিন কোড, 24 বাইট
6A 0A 5E 31 C9 89 F8 99 F7 F6 01 D1 85 C0 75 F7 8D 04 09 99 F7 F7 92 C3
উপরের কোডটি 64-বিট x86 মেশিন কোডে একটি ফাংশন সংজ্ঞায়িত করে যা নির্ধারণ করে যে ইনপুট মানটি তার অঙ্কগুলির যোগফলের দ্বিগুণ দ্বারা বিভাজ্য কিনা। ফাংশনটি সিস্টেম ভি এএমডি 64 কলিং কনভেনশনের সাথে সঙ্গতিপূর্ণ, যাতে এটি কার্যত কোনও ভাষা থেকে কলযোগ্য, ঠিক যেন এটি কোনও সি ফাংশন।
EDI
কলিং কনভেনশন অনুযায়ী এটি নিবন্ধের মাধ্যমে ইনপুট হিসাবে একক পরামিতি নেয় যা পরীক্ষার পূর্ণসংখ্যা। (এটি চ্যালেঞ্জের নিয়মের সাথে সামঞ্জস্যপূর্ণ, ইতিবাচক পূর্ণসংখ্যার হিসাবে ধরে নেওয়া হয় এবং CDQ
আমরা সঠিকভাবে কাজ করতে যে নির্দেশনা ব্যবহার করি তার জন্য এটি প্রয়োজনীয় is )
EAX
কলিং কনভেনশন অনুসারে এটি পুনরায় নিবন্ধে তার ফল দেয় । যদি ইনপুট মান ফলাফলের 0 হতে হবে ছিল তার ডিজিটের যোগফল দ্বারা বিভাজ্য, এবং অন্যথায় নন-জিরো। (মূলত, একটি বিপরীত বুলিয়ান, ঠিক চ্যালেঞ্জের বিধিগুলিতে দেওয়া উদাহরণের মতো))
এর সি প্রোটোটাইপটি হ'ল:
int DivisibleByDoubleSumOfDigits(int value);
প্রতিটি নির্দেশের উদ্দেশ্য সম্পর্কে একটি সংক্ষিপ্ত বিবরণ দিয়ে বর্ণিত অসমাপ্ত সমাবেশ ভাষার নির্দেশাবলী এখানে রয়েছে:
; EDI == input value
DivisibleByDoubleSumOfDigits:
push 10
pop rsi ; ESI <= 10
xor ecx, ecx ; ECX <= 0
mov eax, edi ; EAX <= EDI (make copy of input)
SumDigits:
cdq ; EDX <= 0
div esi ; EDX:EAX / 10
add ecx, edx ; ECX += remainder (EDX)
test eax, eax
jnz SumDigits ; loop while EAX != 0
lea eax, [rcx+rcx] ; EAX <= (ECX * 2)
cdq ; EDX <= 0
div edi ; EDX:EAX / input
xchg edx, eax ; put remainder (EDX) in EAX
ret ; return, with result in EAX
প্রথম ব্লকে, আমরা রেজিস্টারগুলির কিছু প্রাথমিক সূচনা করি:
PUSH
+ + POP
নির্দেশাবলী আরম্ভ করার জন্য একটি ধীর কিন্তু সংক্ষিপ্ত উপায় হিসেবে ব্যবহার করা হয় ESI
10. এই প্রয়োজনীয় কারণ DIV
এক্স 86 উপর নির্দেশ একটি রেজিস্টার প্রতীক প্রয়োজন। (এমন কোনও রূপ নেই যা 10 এর তাত্ক্ষণিক মান দ্বারা বিভক্ত হয়)
XOR
ECX
নিবন্ধকে সাফ করার জন্য একটি ছোট এবং দ্রুত উপায় হিসাবে ব্যবহৃত হয় । এই রেজিস্টারটি আসন্ন লুপের ভিতরে "সঞ্চয়কারী" হিসাবে পরিবেশন করবে।
- অবশেষে, ইনপুট মানটির (থেকে
EDI
) একটি অনুলিপি তৈরি করা হয় এবং এতে সংরক্ষণ করা হয় EAX
, যা আমরা লুপের মধ্য দিয়ে যেতে যেতে আঁটসাঁট হয়ে যাবে।
তারপরে, আমরা লুপিং এবং ইনপুট মানটিতে অঙ্কগুলি সংমিশ্রণ শুরু করি। এটি x86 DIV
নির্দেশের উপর ভিত্তি করে তৈরি করা হয়েছে , যা EDX:EAX
এর অপারেন্ড দ্বারা ভাগ হয়ে যায় EAX
এবং ভাগফলটি এবং বাকী বাক্যটি প্রদান করে EDX
। আমরা এখানে যা করব ইনপুট মানটি 10 দ্বারা বিভক্ত করা হবে যেমন বাকীটি শেষ স্থানে থাকা অঙ্ক (যা আমরা আমাদের সংযোজক রেজিস্টারে যুক্ত করব ECX
), এবং ভাগফল বাকী অঙ্কগুলি।
CDQ
নির্দেশ সেটিং একটি সংক্ষিপ্ত উপায় EDX
0. এটা আসলে করার সাইন-প্রসারিত মান EAX
থেকে EDX:EAX
, যা কি DIV
লভ্যাংশ হিসাবে ব্যবহার করে। আমাদের এখানে আসলে সাইন-এক্সটেনশনের দরকার নেই, কারণ ইনপুট মানটি স্বাক্ষরযুক্ত নয়, তবে ক্লিয়ার CDQ
করতে ব্যবহারের বিপরীতে 1 বাইট , যা 2 বাইট হবে।XOR
EDX
- তারপর আমরা
DIV
IDE EDX:EAX
দ্বারা ESI
(10)।
- বাকী (
EDX
) সংযোজকটিতে যোগ করা হয় ( ECX
)।
EAX
রেজিস্টার (ভাগফল) যদি এটা 0. সমান তাই, আমরা এটা ডিজিটের সব মাধ্যমে করা হয়েছে এবং আমরা মাধ্যমে পড়া কিনা তা দেখতে পরীক্ষা করা হয়। যদি তা না হয় তবে আমাদের যোগফলের আরও বেশি সংখ্যা রয়েছে তাই আমরা লুপের শীর্ষে ফিরে যাই।
লুপ শেষ হওয়ার পরে, আমরা বাস্তবায়ন করি number % ((sum_of_digits)*2)
:
LEA
নির্দেশ অল্প উপায় হিসেবে ব্যবহার করা হয় সংখ্যাবৃদ্ধি ECX
2 দ্বারা (অথবা এবং, equivalently, যোগ ECX
(এই ক্ষেত্রে নিজেই), এবং ফলাফলের সংরক্ষণ একটি ভিন্ন রেজিস্টারে EAX
)।
(আমরা এটিও করতে পারতাম add ecx, ecx
+ xchg ecx, eax
; উভয়ই 3 বাইট, তবে LEA
নির্দেশটি দ্রুত এবং আরও সাধারণ)
- তারপরে, আমরা
CDQ
বিভাগের জন্য প্রস্তুত করতে আবার চেষ্টা করি । কারণ EAX
ইতিবাচক হবে (অর্থাত্ স্বাক্ষরযুক্ত), এটি EDX
আগের মতো শূন্যেরও প্রভাব ফেলে ।
- পরবর্তী বিভাগটি,
EDX:EAX
এবার ইনপুট মান দ্বারা বিভাজন (একটি নিরবচ্ছিন্ন অনুলিপি যার মধ্যে এখনও রয়েছে EDI
)। এটি মডুলোর সমতুল্য, বাকী বাকী অংশের সাথে EDX
। (ভাগফলটিও isোকানো হয়েছে EAX
, তবে আমাদের এটির দরকার নেই))
- পরিশেষে, আমরা
XCHG
(EXCHANGE) বিষয়বস্তু EAX
এবং EDX
। সাধারণত, আপনি MOV
এখানে কিছু করতে পারেন তবে XCHG
এটি কেবলমাত্র 1 বাইট (ধীর হলেও)। কারণ EDX
বিভাগের পরের বাকী অংশগুলি রয়েছে, যদি মানটি সমানভাবে বিভাজ্য বা অন্যথায় শূন্য হয় না তবে এটি 0 হবে। এইভাবে, যখন আমরা RET
পোড়া, EAX
(ফলাফল) 0 হয় যদি ইনপুট মানটি তার অঙ্কগুলির যোগফলের দ্বিগুণ দ্বারা বিভাজ্য হয়, বা অন্যথায় শূন্য নয়।
আশা করি এটি একটি ব্যাখ্যা যথেষ্ট।
এটি স্বল্পতম এন্ট্রি নয়, তবে ওহে, দেখে মনে হচ্ছে এটি অ-গল্ফিংয়ের প্রায় সব ভাষাই মারছে! :-)