এই অনুশীলনীতে আপনি x86-64 অ্যাসেম্বলি ভাষা দ্বারা অনুপ্রাণিত একটি ছোট ভাষার সিনট্যাক্স এবং এক্সিকিউশন মডেল নির্ধারণ করবেন।
লক্ষ্য হলো, একটি সীমাবদ্ধ পরিবেশে কোড কীভাবে লেখা, পার্স ও এক্সিকিউট করা হয়, সেটিকে আনুষ্ঠানিক রূপ দেওয়া।
আপনার অ্যাসেম্বলি কোড লেখা হবে একটি বিশেষ কনস্ট্রাক্টের ভেতরে:
let program := assemble!(
-- assembly code here
)
এই কনস্ট্রাক্টটিকে অবশ্যই একটি প্রোগ্রাম তৈরি করতে হবে, যা এমন একটি ফাংশন সিমুলেট করে, যেটি অ্যাসেম্বলি কোডটি এক্সিকিউট করে একটি মান রিটার্ন করে।
এরপর এই প্রোগ্রামটি নিচের সিনট্যাক্স দিয়ে কল করা হয়, যেখানে a, b, c ইত্যাদি হলো আর্গুমেন্ট:
let result := program(a, b, c, ...)
সব আর্গুমেন্ট এবং রিটার্ন ভ্যালু হলো ৬৪-বিট সাইনড ইন্টিজার। সর্বোচ্চ ৬টি আর্গুমেন্ট ব্যবহার করা যাবে।
রিটার্ন ভ্যালু এবং সব আর্গুমেন্ট রেজিস্টারের মাধ্যমে পাস করা হয়। আপনার ভাষাকে অবশ্যই নিচের রেজিস্টারগুলি সাপোর্ট করতে হবে:
| রেজিস্টার | ভূমিকা |
|---|---|
rdi |
প্রথম আর্গুমেন্ট |
rsi |
দ্বিতীয় আর্গুমেন্ট |
rdx |
তৃতীয় আর্গুমেন্ট |
rcx |
চতুর্থ আর্গুমেন্ট |
r8 |
পঞ্চম আর্গুমেন্ট |
r9 |
ষষ্ঠ আর্গুমেন্ট |
rax |
রিটার্ন ভ্যালু |
ফাংশনে আর্গুমেন্ট পাস করতে ব্যবহৃত না হলে, রেজিস্টারগুলির শুরুর মান ডিফল্ট হিসেবে 0 থাকে।
উদাহরণস্বরূপ, নিচের প্রোগ্রামে rdi-কে 10 দিয়ে এবং rsi-কে -20 দিয়ে ইনিশিয়ালাইজ করা হয়েছে, আর বাকি সব রেজিস্টারের মান 0:
program(10, -20)
প্রোগ্রামের রিটার্ন ভ্যালু সবসময় rax-এ সংরক্ষণ করা হয়।
রেজিস্টারের নাম কেস-ইনসেনসিটিভ।
এর মানে হলো rax, RAX এবং rAx সবই একই রেজিস্টার বোঝায়।
অ্যাসেম্বলি কোডের প্রতিটি লাইন দুই ধরনের হতে পারে:
কোনো ইনস্ট্রাকশন না বদলালে, প্রোগ্রামের এক্সিকিউশন প্রবাহ রৈখিকভাবে এগোতে থাকে। এর মানে হলো, একটি লাইন পুরোপুরি এক্সিকিউট হওয়ার পরেই তার পরের লাইন এক্সিকিউট হয়।
লেবেলের সিনট্যাক্স নিচের মতো:
<label>:
এগুলি কোনো রেজিস্টারের মান বদলায় না, আর কোডের নির্দিষ্ট জায়গাগুলি চিহ্নিত করা ছাড়া প্রোগ্রামে অন্য কোনো প্রভাবও ফেলে না, যাতে ইনস্ট্রাকশনগুলি সেগুলি ব্যবহার করতে পারে।
লেবেল কেস-সেনসিটিভ।
এর মানে হলো Start, start এবং sTart সবই আলাদা লেবেল।
বেশিরভাগ ইনস্ট্রাকশনের সিনট্যাক্স নিচের মতো:
<opcode> <destination>, <source>
opcode বোঝায় কোন অপারেশনটি চালানো হচ্ছে, যা destination আর source অপারেন্ডের মান ব্যবহার করে।
অপারেশনের ফলাফল সংরক্ষণ করা হয় destination অপারেন্ডে।
উদাহরণস্বরূপ, add ইনস্ট্রাকশন destination আর source অপারেন্ডের মান যোগ করে, এবং এই ফলাফলটি destination অপারেন্ডে সংরক্ষণ করে।
destination অপারেন্ড সবসময় একটি রেজিস্টার, আর source অপারেন্ড একটি রেজিস্টার বা একটি লিটারাল সংখ্যা হতে পারে।
আপনার প্রোগ্রামকে এই ইনস্ট্রাকশনগুলি সাপোর্ট করতে হবে:
| অপকোড | যে অপারেশন চালানো হয় |
|---|---|
mov |
destination := source |
add |
destination := destination + source |
sub |
destination := destination - source |
mul |
destination := destination * source |
div |
destination := destination / source |
xor |
destination := destination ^^^ source |
and |
destination := destination &&& source |
or |
destination := destination ||| source |
shl |
destination := destination <<< source |
shr |
destination := destination >>> source |
এগুলি ছাড়াও, আপনার প্রোগ্রামকে দুই-অপারেন্ড cmp ইনস্ট্রাকশনটি সাপোর্ট করতে হবে।
এই ইনস্ট্রাকশন কোনো রেজিস্টার বদলায় না, বরং destination আর source অপারেন্ডের তুলনা করে প্রোগ্রামের অভ্যন্তরীণ অবস্থাকে তিনটি সম্ভাবনার একটিতে সেট করে:
destination > source
destination == source
destination < source
এই অবস্থাটি ভেতরে কীভাবে হিসাব রাখবেন, সেটি আপনার উপর নির্ভর করে।
কিছু ইনস্ট্রাকশন আছে যেগুলি প্রোগ্রামের প্রবাহ বদলে দেয় এবং এক্সিকিউশন কোডের অন্য একটি জায়গায় নিয়ে যায়। এগুলিকে জাম্পিং ইনস্ট্রাকশন বলা হয়।
এগুলির প্রত্যেকটি মাত্র একটি অপারেন্ড নেয়, যা একটি লেবেল এবং জাম্পের লক্ষ্য নির্দেশ করে, অর্থাৎ কোডের যে জায়গা থেকে এক্সিকিউশন আবার চলবে:
<opcode> <label>
jmp ইনস্ট্রাকশন সবসময় লক্ষ্য লেবেলে জাম্প করে।
অন্য জাম্পিং ইনস্ট্রাকশনগুলি কেবল তখনই জাম্প করে, যখন প্রোগ্রামের অভ্যন্তরীণ অবস্থা একটি নির্দিষ্ট মানে সেট করা থাকে।
এর মানে হলো, এগুলির আগে সাধারণত একটি cmp ইনস্ট্রাকশন থাকে।
আপনার প্রোগ্রামকে এই জাম্পিং ইনস্ট্রাকশনগুলি সাপোর্ট করতে হবে:
| ইনস্ট্রাকশন | যে অপারেশন চালানো হয় |
|---|---|
jmp |
শর্তহীন জাম্প। জাম্প সবসময় করা হয় |
je |
অভ্যন্তরীণ অবস্থা সমান হলে জাম্প করে |
jl |
অভ্যন্তরীণ অবস্থা ছোট হলে জাম্প করে |
jg |
অভ্যন্তরীণ অবস্থা বড় হলে জাম্প করে |
ইনস্ট্রাকশনের অপকোড, তা দুই-অপারেন্ড হোক বা এক-অপারেন্ড, কেস-ইনসেনসিটিভ।
এর মানে হলো add, ADD এবং aDd সবই একই ইনস্ট্রাকশন বোঝায়।
Exercism-এ সাইন আপ করুন, Lean ট্র্যাকের 100টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।