যখন কোনও কম্পিউটার কোনও ভেরিয়েবল সঞ্চয় করে, যখন কোনও প্রোগ্রামের ভেরিয়েবলের মান পাওয়ার প্রয়োজন হয় তখন কম্পিউটারটি কীভাবে জানতে পারে যে সেই ভেরিয়েবলের মানটির জন্য মেমরিটি কোথায় দেখতে হবে?
যখন কোনও কম্পিউটার কোনও ভেরিয়েবল সঞ্চয় করে, যখন কোনও প্রোগ্রামের ভেরিয়েবলের মান পাওয়ার প্রয়োজন হয় তখন কম্পিউটারটি কীভাবে জানতে পারে যে সেই ভেরিয়েবলের মানটির জন্য মেমরিটি কোথায় দেখতে হবে?
উত্তর:
আমি আপনাকে কম্পাইলার নির্মাণের দুর্দান্ত বিশ্বের দিকে নজর দেওয়ার পরামর্শ দিচ্ছি! উত্তরটি হ'ল এটি একটি জটিল প্রক্রিয়া।
আপনাকে একটি অন্তর্দৃষ্টি দেওয়ার চেষ্টা করার জন্য, মনে রাখবেন যে পরিবর্তনশীল নামগুলি প্রোগ্রামারটির জন্য রয়েছে there কম্পিউটার শেষ পর্যন্ত সবকিছু ঠিকানায় রূপান্তরিত করবে।
স্থানীয় ভেরিয়েবলগুলি (সাধারণত) স্ট্যাকে সঞ্চিত থাকে: এটি হ'ল তারা ডেটা স্ট্রাকচারের অংশ যা কোনও ফাংশন কলকে উপস্থাপন করে। আমরা কোনও ফাংশনটি (সম্ভবত) সেই ফাংশনটি ব্যবহার করে ব্যবহারযোগ্য ভেরিয়েবলগুলির সম্পূর্ণ তালিকা নির্ধারণ করতে পারি, তাই সংকলকটি দেখতে পারে যে এই ফাংশনের জন্য এটির জন্য কতগুলি ভেরিয়েবল দরকার এবং প্রতিটি ভেরিয়েবলের কতটা স্থান নেয়।
স্ট্যাক পয়েন্টার নামে কিছুটা যাদু আছে, যা একটি নিবন্ধ যা সর্বদা বর্তমান স্ট্যাকটি শুরু হয় তার ঠিকানা সঞ্চয় করে।
প্রতিটি ভেরিয়েবলকে একটি "স্ট্যাক অফসেট" দেওয়া হয়, এটি যেখানে স্ট্যাকের মধ্যে এটি সঞ্চিত থাকে। তারপরে, যখন প্রোগ্রামটির কোনও ভেরিয়েবল অ্যাক্সেস করার প্রয়োজন হয়, তখন এটি মেমরিতে সংরক্ষিত প্রকৃত প্রকৃত স্থান পেতে x
সংকলকটি এর x
সাথে প্রতিস্থাপন করে STACK_POINTER + x_offset
।
উল্লেখ্য যে, এই যখন আপনি ব্যবহার কেন আপনি একটি পয়েন্টার ফিরে পেতে malloc
বা new
C অথবা সি ++ হবে। হেম-বরাদ্দকৃত মানটি ঠিক কোথায় মেমোরিতে রয়েছে তা আপনি নির্ধারণ করতে পারবেন না, সুতরাং আপনাকে এটির একটি পয়েন্টার রাখতে হবে। সেই পয়েন্টারটি স্ট্যাকের মধ্যে থাকবে তবে এটি স্তূপের দিকে নির্দেশ করবে।
ফাংশন কল এবং রিটার্নগুলির জন্য স্ট্যাকগুলি আপডেট করার বিশদটি জটিল, তাই আপনার আগ্রহী হলে আমি ড্রাগন বুক বা টাইগার বুকটি গ্রহণ করবো।
যখন কোনও কম্পিউটার কোনও ভেরিয়েবল সঞ্চয় করে, যখন কোনও প্রোগ্রামের ভেরিয়েবলের মান পাওয়ার প্রয়োজন হয় তখন কম্পিউটারটি কীভাবে জানতে পারে যে সেই ভেরিয়েবলের মানটির জন্য মেমরিটি কোথায় দেখতে হবে?
প্রোগ্রাম এটি বলে। কম্পিউটারগুলিতে স্থানীয়ভাবে "ভেরিয়েবল" ধারণা নেই - এটি পুরোপুরি একটি উচ্চ-স্তরের ভাষার জিনিস!
এখানে একটি সি প্রোগ্রাম রয়েছে:
int main(void)
{
int a = 1;
return a + 3;
}
এবং এখানে সমাবেশ কোডটি এটি সংকলিত হয়েছে: (মন্তব্য দিয়ে শুরু করা ;
)
main:
; {
pushq %rbp
movq %rsp, %rbp
; int a = 1
movl $1, -4(%rbp)
; return a + 3
movl -4(%rbp), %eax
addl $3, %eax
; }
popq %rbp
ret
"Int a = 1;" এর জন্য সিপিইউ নির্দেশনাটি দেখে "ঠিকানায় মান 1 সংরক্ষণ করুন (রেজিস্টার আরবিপি এর মান, বিয়োগ 4)"। এটি 1 মানটি কোথায় সংরক্ষণ করবে তা জানে কারণ প্রোগ্রামটি এটি বলে।
তেমনি, পরবর্তী নির্দেশাবলীতে বলা হয়েছে "ঠিকানাতে মান (রেজিস্টার আরবিপি, বিয়োগ 4) এর নিবন্ধটি রেজিস্টার ইক্সে লোড করুন"। ভেরিয়েবলের মতো জিনিস সম্পর্কে কম্পিউটারের জানা দরকার নেই।
%rsp
করতে সিপিইউর স্ট্যাক পয়েন্টার। %rbp
হ'ল একটি নিবন্ধ যা বর্তমান ফাংশন দ্বারা ব্যবহৃত স্ট্যাকের বিটকে বোঝায়। দুটি রেজিস্টার ব্যবহার করে ডিবাগিং সহজতর হয়।
সংকলক বা দোভাষী যখন কোনও ভেরিয়েবলের ঘোষণার মুখোমুখি হয়, তখন সিদ্ধান্ত নেয় যে সেই ভেরিয়েবলটি সংরক্ষণ করার জন্য এটি কোন ঠিকানা ব্যবহার করবে এবং তারপরে একটি চিহ্ন টেবিলের মধ্যে ঠিকানাটি রেকর্ড করবে। সেই পরিবর্তনশীলটির পরবর্তী উল্লেখগুলির মুখোমুখি হলে, প্রতীক টেবিলের ঠিকানাটি প্রতিস্থাপন করা হয়।
প্রতীক সারণীতে রেকর্ড করা ঠিকানাটি কোনও নিবন্ধ থেকে অফসেট হতে পারে (যেমন স্ট্যাক পয়েন্টার) তবে এটি বাস্তবায়নের বিশদ।
সঠিক পদ্ধতিগুলি আপনি নির্দিষ্টভাবে কী সম্পর্কে কথা বলছেন এবং আপনি কত গভীর যেতে চান তার উপর নির্ভর করে। উদাহরণস্বরূপ, হার্ড ড্রাইভে ফাইল সঞ্চয় করা মেমরিতে কিছু সঞ্চয় করা বা ডাটাবেসে কিছু সঞ্চয় করার চেয়ে আলাদা। যদিও ধারণাগুলি একই রকম। এবং আপনি প্রোগ্রামিং স্তরে এটি কীভাবে করেন এটি কম্পিউটার / আই পর্যায়ে কীভাবে এটি করে তার থেকে আলাদা ব্যাখ্যা।
কম্পিউটারকে ডেটা সন্ধান এবং অ্যাক্সেসের অনুমতি দেওয়ার জন্য বেশিরভাগ সিস্টেমগুলি কোনও ধরণের ডিরেক্টরি / সূচক / রেজিস্ট্রি প্রক্রিয়া ব্যবহার করে। এই সূচী / ডিরেক্টরিতে এক বা একাধিক কী থাকবে এবং ডেটা আসলে ঠিকানাটিতে অবস্থিত (এটি হার্ড ড্রাইভ, র্যাম, ডাটাবেস ইত্যাদি থাকুক)।
কম্পিউটার প্রোগ্রাম উদাহরণ
একটি কম্পিউটার প্রোগ্রাম বিভিন্ন উপায়ে মেমরি অ্যাক্সেস করতে পারে। সাধারণত অপারেটিং সিস্টেম প্রোগ্রামটিকে একটি ঠিকানা স্থান দেয় এবং প্রোগ্রামটি ঠিকানার জায়গার সাহায্যে যা করতে চায় তা করতে পারে। এটি তার স্মৃতি স্পেসের মধ্যে যে কোনও ঠিকানায় সরাসরি লিখতে পারে এবং এটি কীভাবে এটি চায় তার উপর নজর রাখতে পারে। প্রোগ্রামিং ল্যাঙ্গুয়েজ এবং অপারেটিং সিস্টেমের মাধ্যমে, এমনকি কোনও প্রোগ্রামারের পছন্দের কৌশল অনুসারে এটি কখনও কখনও পরিবর্তিত হয়।
অন্য কয়েকটি উত্তরে যেমন উল্লেখ করা হয়েছে, ব্যবহৃত সঠিক কোডিং বা প্রোগ্রামিং আলাদা হয় তবে সাধারণত পর্দার আড়ালে এটি স্ট্যাকের মতো কিছু ব্যবহার করে। এটিতে একটি রেজিস্টার রয়েছে যা মেমরির অবস্থানটি সঞ্চয় করে যেখানে বর্তমান স্ট্যাকটি শুরু হয় এবং তারপরে সেই স্ট্যাকটিতে কোনও ফাংশন বা পরিবর্তনশীল কোথায় তা জানার একটি পদ্ধতি method
অনেকগুলি উচ্চ স্তরের প্রোগ্রামিং ভাষায়, এটি আপনার পক্ষে সমস্ত কিছুর যত্ন নেয়। আপনাকে যা করতে হবে তা হ'ল একটি ভেরিয়েবল ঘোষণা করা এবং সেই পরিবর্তনশীলতে কিছু সঞ্চয় করা এবং এটি আপনার জন্য দৃশ্যের পিছনে প্রয়োজনীয় স্ট্যাক এবং অ্যারে তৈরি করে।
তবে বহুমুখী প্রোগ্রামিংয়ের বিষয়টি বিবেচনা করে সত্যই একটি উত্তর নেই, যেহেতু কোনও প্রোগ্রামার তার বরাদ্দকৃত জায়গার যে কোনও সময় সরাসরি যে কোনও ঠিকানায় সরাসরি লিখতে বেছে নিতে পারেন (ধরে নিলেন যে তিনি প্রোগ্রামিং ভাষা ব্যবহার করছেন যা এটি অনুমতি দেয়)। তারপরে তিনি তার অবস্থানটি একটি অ্যারেতে সঞ্চয় করতে পারতেন, বা এমনকি প্রোগ্রামটিকে হার্ড কোডও (যেমন ভেরিয়েবল "আলফা" সর্বদা স্ট্যাকের শুরুতে সংরক্ষণ করা হয় বা বরাদ্দ মেমরির প্রথম 32 বিটগুলিতে সর্বদা সঞ্চিত থাকে)।
সারাংশ
সুতরাং মূলত, পর্দার আড়ালে কিছু ব্যবস্থা থাকতে হবে যা কম্পিউটারকে ডেটা সঞ্চিত করে বলে। সর্বাধিক জনপ্রিয় উপায়গুলির মধ্যে একটি হ'ল কিছু ধরণের সূচি / ডিরেক্টরি যা কী (গুলি) এবং মেমরির ঠিকানা রাখে। এটি সমস্ত ধরণের উপায়ে প্রয়োগ করা হয় এবং সাধারণত ব্যবহারকারীর কাছ থেকে (এবং এমনকি কখনও কখনও প্রোগ্রামার থেকে এনক্যাপসুলেটেড) থাকে।
তথ্যসূত্র: কম্পিউটারগুলি কীভাবে মনে রাখে যে তারা জিনিসগুলি কোথায় রাখে?
এটি টেমপ্লেট এবং ফর্ম্যাটগুলির কারণে জানে।
প্রোগ্রাম / ফাংশন / কম্পিউটার আসলে কোথায় থাকে তা জানে না। এটি কেবল প্রত্যাশা করে যে কোনও কিছু নির্দিষ্ট স্থানে থাকবে। একটি উদাহরণ ব্যবহার করা যাক।
class simpleClass{
public:
int varA=58;
int varB=73;
simpleClass* nextObject=NULL;
};
আমাদের নতুন শ্রেণীর 'সিম্পলক্লাস'-এ 3 টি গুরুত্বপূর্ণ ভেরিয়েবল রয়েছে - দুটি পূর্ণসংখ্যার যাতে আমাদের যখন প্রয়োজন হয় তখন কিছু ডেটা থাকতে পারে এবং অন্য' সিম্পিক্লাস অবজেক্ট'-এর পয়েন্টার। আসুন ধরে নেওয়া যাক আমরা সরলতার জন্য 32-বিট মেশিনে আছি। 'জিসিসি' বা অন্য কোনও 'সি' সংকলক কিছু ডেটা বরাদ্দ করার জন্য আমাদের সাথে কাজ করার জন্য একটি টেম্পলেট তৈরি করে।
সাধারণ প্রকার
প্রথমত, যখন কেউ 'int' এর মতো সাধারণ টাইপের জন্য কোনও কীওয়ার্ড ব্যবহার করে তখন এক্সিকিউটেবল ফাইলের '.ডাটা' বা '.bss' বিভাগে সংকলক দ্বারা একটি নোট তৈরি করা হয় যাতে এটি যখন অপারেটিং সিস্টেমের দ্বারা চালিত হয়, তখন ডেটা হয় প্রোগ্রামে উপলব্ধ। 'ইনট' কীওয়ার্ডটি 4 বাইট (32 বিট) বরাদ্দ করবে, যখন একটি 'লং ইনট' 8 বাইট (64 বিট) বরাদ্দ করবে।
কখনও কখনও, সেল-বাই-সেল পদ্ধতিতে, মেমরিটিতে লোড করার কথা নির্দেশের পরে ঠিক একটি পরিবর্তনশীল উপস্থিত হতে পারে, সুতরাং এটি সিউডো-অ্যাসেমব্লিকে দেখায়:
...
clear register EAX
clear register EBX
load the immediate (next) value into EAX
5
copy the value in register EAX to register EBX
...
এটি EAX এর পাশাপাশি EBX এর '5' মানের সাথে শেষ হবে।
প্রোগ্রামটি কার্যকর করার সময়, প্রতিটি নির্দেশ '5' ব্যতীত প্রতিটি নির্দেশই কার্যকর করা হয়, কারণ তাত্ক্ষণিক লোড এটি উল্লেখ করে এবং এতে সিপিইউ এড়িয়ে যায় ip
এই পদ্ধতির ক্ষতিটি হ'ল এটি কেবল ধ্রুবকদের জন্য বাস্তবই বাস্তব, যেহেতু আপনার কোডের মাঝে অ্যারে / বাফার / স্ট্রিংগুলি রাখা অবৈধ হবে। সুতরাং, সাধারণত, বেশিরভাগ ভেরিয়েবলগুলি প্রোগ্রাম শিরোনামে রাখা হয়।
যদি এই গতিশীল ভেরিয়েবলগুলির মধ্যে একটিতে অ্যাক্সেসের প্রয়োজন হয় তবে কেউ তাৎক্ষণিক মানটিকে এমনভাবে আচরণ করতে পারে যেন এটি পয়েন্টার হিসাবে থাকে:
...
clear register EAX
clear register EBX
load the immediate value into EAX
0x0AF2CE66 (Let's say this is the address of a cell containing '5')
load the value pointed to by EAX into EBX
...
এটি রেজিস্টার EAX এর '0x0AF2CE66' মান এবং EBX রেজিস্টারে '5' এর মান দিয়ে শেষ হবে। একসাথে নিবন্ধগুলিতে মান যুক্ত করতে পারে, তাই আমরা এই পদ্ধতিটি ব্যবহার করে কোনও অ্যারে বা স্ট্রিংয়ের উপাদানগুলি সন্ধান করতে সক্ষম হব।
আর একটি গুরুত্বপূর্ণ বিষয় হ'ল একইরূপে ঠিকানাগুলি ব্যবহার করার সময় কেউ মানগুলি সঞ্চয় করতে সক্ষম হয়, যাতে পরবর্তীকালে সেই কক্ষগুলিতে মানগুলি উল্লেখ করা যায়।
জটিল প্রকারের
যদি আমরা এই শ্রেণীর দুটি বস্তু তৈরি করি:
simpleClass newObjA;
simpleClass newObjB;
তারপরে আমরা দ্বিতীয় অবজেক্টের জন্য এটি প্রথম ক্ষেত্রের জন্য উপলব্ধ ক্ষেত্রের জন্য একটি পয়েন্টার নির্ধারণ করতে পারি:
newObjA.nextObject=&newObjB;
এখন প্রোগ্রামটি প্রথম অবজেক্টের পয়েন্টার ক্ষেত্রের মধ্যে দ্বিতীয় বস্তুর ঠিকানা খুঁজে পাওয়ার আশা করতে পারে। স্মৃতিতে, এটিকে এমন কিছু দেখাচ্ছে:
newObjA: 58
73
&newObjB
...
newObjB: 58
73
NULL
এখানে একটি অতি গুরুত্বপূর্ণ বিষয় লক্ষণীয় যে 'newObjA' এবং 'newObjB' এর সংকলন করার পরে তাদের নাম নেই। এগুলি কেবলমাত্র এমন জায়গাগুলি যেখানে আমরা কিছু ডেটা থাকার আশা করি। সুতরাং, যদি আমরা & newObjA তে 2 টি কোষ যুক্ত করি তবে আমরা সেই ঘরটি খুঁজে পাই যা 'নেক্সটবজেক্ট' হিসাবে কাজ করে। সুতরাং, আমরা যদি 'newObjA' এর ঠিকানাটি জানি এবং যেখানে 'নেক্সটবজেক্ট' সেলটি এটি সম্পর্কিত, তবে আমরা 'newObjB' এর ঠিকানাটি জানতে পারি:
...
load the immediate value into EAX
&newObjA
add the immediate value to EAX
2
load the value in EAX into EBX
এটি 'EAX' এ '2 + & newObjA' এবং 'EBX' এ 'এবং newObjB' দিয়ে শেষ হবে।
টেমপ্লেট / ফর্ম্যাট
সংকলকটি যখন শ্রেণীর সংজ্ঞাটি সংকলন করে, তখন এটি প্রকৃতপক্ষে বিন্যাস তৈরির উপায়, বিন্যাসে লেখার একটি উপায় এবং বিন্যাস থেকে পড়ার উপায় সংকলিত হয়।
উপরের উদাহরণটি দুটি 'ইনট' ভেরিয়েবল সহ একক-সংযুক্ত-তালিকার টেম্পলেট। বাইনারি এবং এন-অ্যারি গাছগুলির পাশাপাশি গতিশীল মেমরির বরাদ্দের জন্য এই ধরণের নির্মাণগুলি খুব গুরুত্বপূর্ণ। এন-আরি গাছগুলির ব্যবহারিক প্রয়োগগুলি ফাইলগুলি, ডিরেক্টরিগুলি বা ড্রাইভার / অপারেটিং সিস্টেম দ্বারা স্বীকৃত অন্যান্য দৃষ্টান্তগুলিতে নির্দেশিত ডিরেক্টরিগুলির সমন্বয়ে ফাইল সিস্টেম থাকে।
সমস্ত উপাদানের অ্যাক্সেসের জন্য, কাঠামোটির উপরে এবং নীচে একটি ইঞ্চিওয়ালা কীভাবে কাজ করে তা সম্পর্কে ভাবুন। এইভাবে, প্রোগ্রাম / ফাংশন / কম্পিউটার কিছুই জানে না, এটি কেবল ডেটাটি সরানোর জন্য নির্দেশাবলী কার্যকর করে।