বেশিরভাগ ক্ষেত্রে, কিছু কার্য সম্পাদন করার সর্বোত্তম উপায়টি সেই প্রসঙ্গের উপর নির্ভর করতে পারে যেখানে টাস্কটি সম্পাদিত হয়। যদি একটি রুটিন অ্যাসেম্বলি ভাষায় রচিত হয়, তবে সাধারণত নির্দেশের অনুক্রমের প্রসঙ্গে ভিত্তিতে বৈচিত্রময় করা সম্ভব হবে না। একটি সাধারণ উদাহরণ হিসাবে, নিম্নলিখিত সহজ পদ্ধতিটি বিবেচনা করুন:
inline void set_port_high(void)
{
(*((volatile unsigned char*)0x40001204) = 0xFF);
}
উপরোক্ত প্রদত্ত 32-বিট এআরএম কোডের জন্য একটি সংকলক সম্ভবত এটিকে এমন কিছু হিসাবে রেন্ডার করবে:
ldr r0,=0x40001204
mov r1,#0
strb r1,[r0]
[a fourth word somewhere holding the constant 0x40001204]
অথবা সম্ভবত
ldr r0,=0x40001000 ; Some assemblers like to round pointer loads to multiples of 4096
mov r1,#0
strb r1,[r0+0x204]
[a fourth word somewhere holding the constant 0x40001000]
এটি হ্যান্ডেল-এসেম্বল কোডে কিছুটা অনুকূলিত হতে পারে, যেমন হয়:
ldr r0,=0x400011FF
strb r0,[r0+5]
[a third word somewhere holding the constant 0x400011FF]
অথবা
mvn r0,#0xC0 ; Load with 0x3FFFFFFF
add r0,r0,#0x1200 ; Add 0x1200, yielding 0x400011FF
strb r0,[r0+5]
উভয় হাতে জড়িত পদ্ধতির জন্য 16 টির পরিবর্তে 12 বাইট কোড স্পেসের প্রয়োজন হবে; পরেরটি একটি "যুক্ত" এর সাথে "লোড" প্রতিস্থাপন করবে, যা একটি এআরএম 7-টিডিএমআইতে দুটি চক্র দ্রুত চালিত করবে। কোডটি যদি এমন কোনও প্রসঙ্গে কার্যকর করা যাচ্ছিল যেখানে r0 জানা ছিল না / জানা নেই - সংবিধানের ভাষা সংস্করণগুলি সংকলিত সংস্করণটির চেয়ে কিছুটা ভাল হতে পারে। অন্যদিকে, ধরুন যে সংকলকটি জানত যে কিছু রেজিস্টার [উদাহরণস্বরূপ r5] পছন্দসই ঠিকানার 0x40001204 [উদাহরণস্বরূপ 0x40001000] এর 2047 বাইটের মধ্যে একটি মান রাখতে চলেছে এবং আরও জানত যে আরও কিছু নিবন্ধক [যেমন r7] যাচ্ছেন এমন মান ধরে রাখতে যার কম বিট 0xFF ছিল। সেক্ষেত্রে একটি সংকলক কোডটির সি সংস্করণটিকে কেবলমাত্র অনুকূলিত করতে পারে:
strb r7,[r5+0x204]
হ্যান্ড-অপ্টিমাইজড অ্যাসেমব্লিং কোডের চেয়েও অনেক খাটো এবং দ্রুত। আরও ধরা যাক, সেট_পোর্ট_পরে প্রসঙ্গটি ঘটেছে:
int temp = function1();
set_port_high();
function2(temp); // Assume temp is not used after this
এম্বেড থাকা সিস্টেমের জন্য কোডিং করার সময় মোটেই অনুচ্চার্য নয়। যদি set_port_high
অ্যাসেম্বলি কোডে লেখা থাকে, সংকলকটি function1
সমাবেশ কোডটি আহ্বান করার আগে আর কোথাও আর -0 (যা থেকে প্রত্যাবর্তনের মান ধারণ করে ) নিয়ে যেতে হবে, এবং তারপরে সেই মানটি r0-এ ফিরে যেতে function2
হবে (যেহেতু এটির প্রথম প্যারামিটারটি r0 তে আশা করবে), সুতরাং "অনুকূলিত" সমাবেশের কোডটির জন্য পাঁচটি নির্দেশাবলীর প্রয়োজন। সংকলকটি ঠিকানা বা সংরক্ষণের মান রাখার জন্য কোনও রেজিস্টারগুলি না জানলেও এর চার-নির্দেশাবলীর সংস্করণ (এটি যে কোনও উপলভ্য রেজিস্টারগুলি ব্যবহার করার জন্য অভিযোজিত করতে পারে - প্রয়োজনে r0 এবং r1 নয়) "অনুকূলিত" সমাবেশকে পরাজিত করবে ভাষা সংস্করণ। পূর্বে বর্ণিত অনুসারে যদি সংকলকটির r5 এবং r7 তে প্রয়োজনীয় ঠিকানা এবং ডেটা থাকে, function1
তবে সেগুলি রেজিস্টারগুলিতে পরিবর্তন করা হত না, এবং সুতরাং এটি প্রতিস্থাপন করতে পারেset_port_high
একটি একক strb
নির্দেশের সাথে - "হ্যান্ড-অপটিমাইজড" সমাবেশ কোডের চেয়ে চারটি নির্দেশ ছোট এবং দ্রুত smaller
নোট করুন যে হ্যান্ড-অপ্টিমাইজড অ্যাসেমব্লিং কোড প্রায়শই এমন ক্ষেত্রে একটি সংকলককে কার্যকর করতে পারে যেখানে প্রোগ্রামার সুনির্দিষ্ট প্রোগ্রামের প্রবাহটি জানে, তবে সংস্থাপকরা সেই ক্ষেত্রে প্রাসঙ্গিকভাবে আলোকিত করে যেখানে কোডের টুকরোটি প্রাসঙ্গিকতার আগে জানা যায়, বা যেখানে উত্স কোডের এক অংশ হতে পারে একাধিক প্রসঙ্গ থেকে আহ্বান জানানো হয়েছে [যদি set_port_high
কোডের পঞ্চাশটি পৃথক স্থানে ব্যবহার করা হয় তবে সংকলক স্বতন্ত্রভাবে সিদ্ধান্ত নিতে পারে যে প্রত্যেকটি কীভাবে এটি প্রসারিত করতে পারে]।
সাধারণভাবে, আমি প্রস্তাব দেব যে সংসদীয় ভাষা সেই ক্ষেত্রে সর্বাধিক কর্মক্ষমতা উন্নতি করতে উপযুক্ত যেখানে কোডের প্রতিটি অংশকে খুব সীমিত সংখ্যার সাথে সংযোগ করা যেতে পারে, এবং এমন জায়গাগুলিতে পারফরম্যান্সের জন্য ক্ষতিকারক হতে প্রস্তুত যেখানে কোনও অংশ রয়েছে piece কোড অনেক বিভিন্ন প্রসঙ্গে থেকে যোগাযোগ করা যেতে পারে। মজার বিষয় (এবং সুবিধাজনকভাবে) যেগুলি ক্ষেত্রে কার্য সম্পাদনের পক্ষে সমাবেশ সবচেয়ে উপকারী তা প্রায়শই সেই ক্ষেত্রে হয় যেখানে কোডটি সবচেয়ে সহজ এবং সহজভাবে পড়তে পারে। অ্যাসেম্বলি ভাষার কোডগুলি যে জায়গাগুলি গুয়ে মেসে পরিণত করবে সেগুলি প্রায়শই এমন হয় যেখানে সমাবেশে লেখা ক্ষুদ্রতম কর্মক্ষমতা সুবিধা দেয় offer
[মাইনর নোট: এমন কয়েকটি জায়গা রয়েছে যেখানে অ্যাসেমব্লি কোডটি হাইপার-অপ্টিমাইজড গুই গণ্ডগোলের জন্য ব্যবহার করা যেতে পারে; উদাহরণস্বরূপ, এআরএমের জন্য র্যামের কাছ থেকে একটি শব্দ আনতে এবং মূল্যটির উপরের ছয়টি বিটের উপর ভিত্তি করে প্রায় বারোটি রুটিনগুলির মধ্যে একটি নির্বাহ করার জন্য কোডের এক টুকরোটি করেছিলাম (একই মানটিতে ম্যাপযুক্ত অনেক মান)) আমি মনে করি যে আমি এই কোডটি এমন কিছুতে অনুকূলিত করেছি:
ldrh r0,[r1],#2! ; Fetch with post-increment
ldrb r1,[r8,r0 asr #10]
sub pc,r8,r1,asl #2
আর 8 রেজিস্টার সর্বদা মূল প্রেরণের টেবিলের ঠিকানা রাখে (লুপের মধ্যে যেখানে কোডটি তার সময়ের 98% সময় ব্যয় করে, কিছুই অন্য কোনও উদ্দেশ্যে কখনও ব্যবহার করে না); সমস্ত 64 টি এন্ট্রি তার আগে 256 বাইটে ঠিকানাগুলিতে উল্লেখ করেছে। যেহেতু প্রাথমিক লুপটি বেশিরভাগ ক্ষেত্রে প্রায় 60 টি চক্রের কঠোর প্রয়োগের সময়সীমা ছিল তাই নয়-চক্রটি আনতে এবং পাঠানো সেই লক্ষ্যটি অর্জনের জন্য খুব সহায়ক ছিল। 256 32-বিট ঠিকানার একটি টেবিল ব্যবহার করা এক চক্র দ্রুততর হতে পারে তবে 1KB খুব মূল্যবান র্যামের গ্যাবলড হত [ফ্ল্যাশটিতে একাধিক অপেক্ষার অবস্থান যুক্ত করা হত]। 32৪-বিট অ্যাড্রেস ব্যবহারের জন্য আনতে হবে এমন শব্দ থেকে কিছু বিটকে মুখোশ দেওয়ার জন্য একটি নির্দেশ যুক্ত করতে হবে এবং আমি যে টেবিলটি ব্যবহার করেছি তা তার চেয়ে আরও বেশি 192 বাইট গাবলড হয়ে থাকতে পারে। 8-বিট অফসেটের সারণীটি ব্যবহার করে খুব কমপ্যাক্ট এবং দ্রুত কোড পাওয়া গেছে, তবে এমন কিছু নয় যা আমি আশা করি যে সংকলকটি কখনই সামনে আসবে; আমি কোনও সংকলক টেবিলের ঠিকানাটি ধরে রাখার জন্য একটি "নিখরচায়" একটি নিবন্ধক উত্সর্গ করার আশাও করব না।
উপরের কোডটি একটি স্ব-অন্তর্ভুক্ত সিস্টেম হিসাবে চালানোর জন্য ডিজাইন করা হয়েছিল; এটি পর্যায়ক্রমে সি কোড কল করতে পারে, তবে কেবলমাত্র নির্দিষ্ট সময়ে যখন হার্ডওয়্যারটি নিরাপদে যোগাযোগ করে তা নিরাপদ অবস্থায় প্রতি 16 মিনিটে দুটি-এক-মিলিসেকেন্ড অন্তর অন্তর একটি "অলস" অবস্থানে স্থাপন করতে পারে।