ট্র্যাক
/
Lean
Lean
/
অনুশীলনী
/
অ্যাসেম্বল করা
অ্যাসেম্বল করা

অ্যাসেম্বল করা

কঠিন

নির্দেশনা

এই অনুশীলনীতে আপনি 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-এ সংরক্ষণ করা হয়।

Note

রেজিস্টারের নাম কেস-ইনসেনসিটিভ। এর মানে হলো rax, RAX এবং rAx সবই একই রেজিস্টার বোঝায়।

অ্যাসেম্বলি কোড

অ্যাসেম্বলি কোডের প্রতিটি লাইন দুই ধরনের হতে পারে:

  • লেবেল প্রোগ্রামের নির্দিষ্ট কিছু জায়গা চিহ্নিত করে, যাতে কিছু ইনস্ট্রাকশন সেগুলি ব্যবহার করতে পারে।
  • ইনস্ট্রাকশন সেই অপারেশনগুলিকে বোঝায়, যা প্রোগ্রাম চালায়।

কোনো ইনস্ট্রাকশন না বদলালে, প্রোগ্রামের এক্সিকিউশন প্রবাহ রৈখিকভাবে এগোতে থাকে। এর মানে হলো, একটি লাইন পুরোপুরি এক্সিকিউট হওয়ার পরেই তার পরের লাইন এক্সিকিউট হয়।

লেবেল

লেবেলের সিনট্যাক্স নিচের মতো:

<label>:

এগুলি কোনো রেজিস্টারের মান বদলায় না, আর কোডের নির্দিষ্ট জায়গাগুলি চিহ্নিত করা ছাড়া প্রোগ্রামে অন্য কোনো প্রভাবও ফেলে না, যাতে ইনস্ট্রাকশনগুলি সেগুলি ব্যবহার করতে পারে।

Note

লেবেল কেস-সেনসিটিভ। এর মানে হলো 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 অভ্যন্তরীণ অবস্থা বড় হলে জাম্প করে
Note

ইনস্ট্রাকশনের অপকোড, তা দুই-অপারেন্ড হোক বা এক-অপারেন্ড, কেস-ইনসেনসিটিভ। এর মানে হলো add, ADD এবং aDd সবই একই ইনস্ট্রাকশন বোঝায়।

GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
Lean Exercism

অ্যাসেম্বল করা শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, Lean ট্র্যাকের 100টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।