প্রোগ্রামের স্ট্যাক থেকে ভেরিয়েবলগুলি কীভাবে সংরক্ষণ করা হয় এবং পুনরুদ্ধার করা হয়?


47

এই প্রশ্নের নিষ্প্রভতার জন্য অগ্রিম ক্ষমা চাই। আমি একজন 50 বছর বয়সী শিল্পী যিনি প্রথমবারের মতো কম্পিউটারগুলি সঠিকভাবে বুঝতে চেষ্টা করছেন trying সুতরাং এখানে যায়।

আমি কম্পাইলার দ্বারা কীভাবে ডেটা টাইপ এবং ভেরিয়েবলগুলি পরিচালনা করা হয় তা বোঝার চেষ্টা করছি (খুব সাধারণ অর্থে, আমি জানি এটির অনেক কিছুই আছে)। "স্ট্যাক" এবং মানের ধরণের স্টোরেজ এবং "হিপ" এবং রেফারেন্সের ধরণের স্টোরেজ (উদ্ধৃতি চিহ্নগুলি বোঝানোর জন্য বোঝানো হচ্ছে যে আমি এই শর্তাদি বিমূর্ততাগুলি ব্যবহার করি এবং না আমি যেমন এই প্রশ্নটি তৈরি করছি তেমন সরল প্রসঙ্গে খুব আক্ষরিক অর্থে গ্রহণ করা)। যাইহোক, আমার সরল ধারণাটি হ'ল বুলিয়ান এবং পূর্ণসংখ্যার মতো প্রকারগুলি "স্ট্যাক" এ চালায় কারণ তারা পারে, কারণ তারা স্টোরেজ স্পেসের দিক দিয়ে পরিচিত সত্তা, এবং সেই অনুযায়ী তাদের ক্ষেত্রটি সহজেই নিয়ন্ত্রণ করা হয়।

তবে আমি যা পাই না তা হ'ল স্ট্যাকের চলকগুলি কীভাবে কোনও অ্যাপ্লিকেশন দ্বারা পড়ে - যদি আমি ঘোষণা করে এবং xএকটি পূর্ণসংখ্যা হিসাবে নির্ধারণ করি , বলি x = 3, এবং স্ট্যাকটি স্ট্যাকের উপর সংরক্ষিত থাকে এবং তার মান 3সেখানে সংরক্ষণ করা হয় এবং তারপরে একই ফাংশনটি আমি ঘোষণা করি এবং নির্ধারণ করি y, বলি 4, এবং তারপরে আমি এর পরে xঅন্য অভিব্যক্তিতে ব্যবহার করি (বলুন z = 5 + x) প্রোগ্রামটি যখন নীচে থাকে তখন xমূল্যায়ন করার জন্য কীভাবে পড়তে পারেzyস্ট্যাকের উপর? আমি স্পষ্টত কিছু মিস করছি। এটি কি স্ট্যাকের অবস্থানটি কেবলমাত্র ভেরিয়েবলের আজীবন / সুযোগ সম্পর্কে এবং পুরো স্ট্যাকটি আসলে সমস্ত সময় প্রোগ্রামে অ্যাক্সেসযোগ্য? যদি তা হয় তবে এর অর্থ কি আরও কিছু সূচক রয়েছে যা মানগুলি পুনরুদ্ধার করার জন্য স্ট্যাকের কেবলমাত্র ভেরিয়েবলের ঠিকানাগুলি ধারণ করে? তবে আমি ভেবেছিলাম স্ট্যাকের পুরো বিন্দুটি হ'ল মানগুলি ভেরিয়েবল ঠিকানার মতো একই জায়গায় সংরক্ষণ করা হয়েছিল? আমার শঙ্কিত মনে হ'ল যদি এই অন্য সূচকটি থাকে তবে আমরা গাদা জাতীয় কিছু নিয়ে কথা বলছি? আমি স্পষ্টতই খুব বিভ্রান্ত, এবং আমি আশা করছি আমার সরল প্রশ্নটির একটি সহজ উত্তর আছে।

এই পর্যন্ত পড়ার জন্য ধন্যবাদ।


7
@ fade2black আমি একমত নই - গুরুত্বপূর্ণ বিষয়গুলির সংক্ষিপ্তসার যুক্তিসঙ্গত দৈর্ঘ্যের একটি উত্তর দেওয়া সম্ভব উচিত should
ডেভিড রিচার্বি

9
আপনি conflating অত্যন্ত সাধারণ ত্রুটি তৈরি করছেন মান ধরনের সঙ্গে যেখানে এটি সংরক্ষণ করা হয় । বুলস স্ট্যাকের উপরে চলে যায় তা বলা সহজ। বুলগুলি ভেরিয়েবলগুলিতে যায় এবং ভেরিয়েবলগুলি স্ট্যাকের উপরে চলে যায় যদি তাদের জীবনকাল সংক্ষিপ্ত হিসাবে পরিচিত হয় , এবং স্তূপে যদি তাদের জীবনকাল সংক্ষিপ্ত হিসাবে পরিচিত না হয়। এটি সি # এর সাথে কীভাবে সম্পর্কিত তা নিয়ে কিছু চিন্তাভাবনার জন্য, দেখুন ব্লগস.এমএসএনএন.মাইক্রোসফট
এরিক লিপার্ট

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

5
এছাড়াও: নতুন কিছু শেখার উদ্যোগ নেওয়া এবং কোনও ভাষার বাস্তবায়ন বিশদ অনুসন্ধানের জন্য আমি আপনাকে সাধুবাদ জানাই। আপনি এখানে একটি আকর্ষণীয় হোঁচট খাচ্ছেন: আপনি বুঝতে পারেন যে একটি বিমূর্ত ডেটা টাইপ হিসাবে স্ট্যাক কী, তবে অ্যাক্টিভেশন এবং ধারাবাহিকতা পুনরুদ্ধার করার জন্য প্রয়োগের বিশদ হিসাবে নয় । পরেরটি স্ট্যাক বিমূর্ত তথ্য প্রকারের নিয়মগুলি অনুসরণ করে না ; এটি তাদেরকে নিয়ম হিসাবে নির্দেশিকাগুলির চেয়ে বেশি আচরণ করে। প্রোগ্রামিং ভাষাগুলির পুরো বিষয়টি হ'ল এটি নিশ্চিত করা যে প্রোগ্রামিংয়ের সমস্যাগুলি সমাধান করার জন্য আপনাকে এই বিমূর্ত-দূরে বিশদটি বুঝতে হবে না।
এরিক লিপার্ট

4
ধন্যবাদ এরিক, সাভা, থাম্বনেল, এই মন্তব্যগুলি এবং উল্লেখগুলি অত্যন্ত কার্যকর। আমার মত সবসময় মনে হয় আপনার মতো লোকেরা যখন আমার মতো কোনও প্রশ্ন দেখেন তখন অবশ্যই অভ্যন্তরীণভাবে হাহাকার করা উচিত, তবে দয়া করে উত্তর পাওয়ার ক্ষেত্রে প্রচুর উত্তেজনা এবং তৃপ্তি জানুন!
সেলিন অ্যাটউড

উত্তর:


24

স্ট্যাকের উপর স্থানীয় ভেরিয়েবলগুলি সংরক্ষণ করা একটি বাস্তবায়নের বিশদ - মূলত একটি অপ্টিমাইজেশন। আপনি এটি এইভাবে ভাবতে পারেন। কোনও ফাংশনে প্রবেশ করার সময়, সমস্ত স্থানীয় ভেরিয়েবলের জন্য স্থান কোথাও বরাদ্দ করা হয়। এরপরে আপনি সমস্ত ভেরিয়েবল অ্যাক্সেস করতে পারবেন, যেহেতু আপনি কোনওভাবে তাদের অবস্থান জানেন (এটি বরাদ্দের প্রক্রিয়ার অংশ। কোনও ফাংশন ছেড়ে যাওয়ার সময়, স্থানটি deallocated (মুক্ত হয়)।

স্ট্যাকটি এই প্রক্রিয়াটি বাস্তবায়নের একটি উপায় - আপনি এটিকে এক ধরণের "ফাস্ট হিপ" হিসাবে ভাবতে পারেন যার আকার সীমিত এবং এটি কেবলমাত্র ছোট ভেরিয়েবলের জন্য উপযুক্ত। অতিরিক্ত অপ্টিমাইজেশন হিসাবে, সমস্ত স্থানীয় ভেরিয়েবলগুলি একটি ব্লকে সংরক্ষণ করা হয়। যেহেতু প্রতিটি স্থানীয় ভেরিয়েবলের আকার জানা থাকে তাই আপনি ব্লকের প্রতিটি ভেরিয়েবলের অফসেট জানেন এবং আপনি কীভাবে এটিকে অ্যাক্সেস করবেন। এটি হিপগুলিতে বরাদ্দকৃত ভেরিয়েবলের বিপরীতে, যার ঠিকানাগুলি নিজেই অন্যান্য ভেরিয়েবলগুলিতে সঞ্চয় করা হয়।

আপনি স্ট্যাকটি ক্লাসিক্যাল স্ট্যাকের ডেটা কাঠামোর সাথে খুব গুরুত্বপূর্ণ, একটি গুরুত্বপূর্ণ পার্থক্য সহ: ভাবতে পারেন: আপনাকে স্ট্যাকের শীর্ষের নীচে আইটেমগুলি অ্যাক্সেস করার অনুমতি দেওয়া হয়েছে। প্রকৃতপক্ষে, আপনি উপর থেকে ম আইটেম অ্যাক্সেস করতে পারেন । এইভাবে আপনি পুশিং এবং পপিংয়ের মাধ্যমে আপনার সমস্ত স্থানীয় ভেরিয়েবল অ্যাক্সেস করতে পারবেন। কেবলমাত্র ঠেলাঠেলি করা হচ্ছে ফাংশনটিতে প্রবেশ করা এবং ফাংশনটি ছেড়ে যাওয়ার পরে পপিং করা।k

পরিশেষে, আমি উল্লেখ করতে পারি যে অনুশীলনে, স্থানীয় ভেরিয়েবলগুলির কয়েকটি রেজিস্টারে সংরক্ষণ করা হয়। এটি যেহেতু নিবন্ধগুলিতে অ্যাক্সেস স্ট্যাকের অ্যাক্সেসের চেয়ে দ্রুত। এটি স্থানীয় ভেরিয়েবলের জন্য একটি স্থান প্রয়োগের অন্য উপায়। আবার, আমরা ঠিক জানি কোথায় কোন ভেরিয়েবল সংরক্ষণ করা হয় (এবার অফসেটের মাধ্যমে নয়, তবে একটি নিবন্ধকের নামে) এবং এই ধরণের সঞ্চয়স্থান কেবলমাত্র ছোট ডেটার জন্য উপযুক্ত।


1
"একটি ব্লকে বরাদ্দ করা" হ'ল আরও একটি বাস্তবায়ন বিশদ। যদিও তাতে কিছু আসে যায় না। সংকলকটি স্থানীয় ভেরিয়েবলগুলির জন্য কীভাবে মেমরির প্রয়োজন তা জানে, এটি সেই মেমরিটিকে এক বা একাধিক ব্লক বরাদ্দ করে এবং তারপরে সেই মেমরিতে স্থানীয় ভেরিয়েবলগুলি তৈরি করে।
MSalters

ধন্যবাদ, সংশোধন। প্রকৃতপক্ষে, এই "ব্লক "গুলির কয়েকটি কেবল নিবন্ধভুক্ত।
যুবাল ফিল্মাস

1
রিটার্ন ঠিকানাগুলি সংরক্ষণ করার জন্য আপনার কেবল সত্যিকারের স্ট্যাকের প্রয়োজন। আপনি স্তূপে সহজেই স্ট্যাক ছাড়াই পুনরাবৃত্তি বাস্তবায়ন করতে পারেন, গাদাতে ফেরতের ঠিকানায় একটি পয়েন্টার দিয়ে passing
যুবাল ফিল্মাস

1
@ মাইককারন স্ট্যাকগুলির পুনরাবৃত্তির সাথে প্রায় কিছুই করার নেই। আপনি অন্যান্য প্রয়োগের কৌশলগুলিতে কেন "ভেরিয়েবলগুলি উড়িয়ে দেবেন"?
বাগানের মাথা

1
@ গ্রেডেনহেড সর্বাধিক সুস্পষ্ট বিকল্প (এবং যেটি আসলে ব্যবহৃত / ব্যবহৃত হয়েছিল) তা হ'ল স্থবিরভাবে প্রতিটি পদ্ধতির ভেরিয়েবলগুলি বরাদ্দ করা। দ্রুত, সহজ, পূর্বাভাসযোগ্য ... তবে কোনও পুনরাবৃত্তি বা পুনরায় প্রবেশের অনুমতি নেই। এটি এবং প্রচলিত স্ট্যাক অবশ্যই একমাত্র বিকল্প নয় (ডায়নামিকভাবে সবকিছু বরাদ্দ করা অন্য একটি), তবে স্ট্যাকগুলি
ন্যায্য

23

রয়ে yস্ট্যাক শারীরিকভাবে বাধা দেয় না xঅ্যাক্সেস করা, যা, হিসাবে আপনি নির্দিষ্ট, কম্পিউটার অন্যান্য স্ট্যাকগুলি থেকে আলাদা stacks তোলে থেকে।

যখন একটি প্রোগ্রাম সংকলিত হয়, স্ট্যাকের ভেরিয়েবলের অবস্থানগুলি পূর্বনির্ধারিত (কোনও ফাংশনের প্রসঙ্গে)। আপনার উদাহরণস্বরূপ, যদি স্ট্যাকটিতে xএকটি y"শীর্ষে" থাকে তবে প্রোগ্রামটি আগে থেকেই জানে যে xফাংশনের অভ্যন্তরে স্ট্যাকের শীর্ষের নীচে 1 আইটেম থাকবে। যেহেতু কম্পিউটার হার্ডওয়্যার স্ট্যাকের উপরের নীচে 1 আইটেমটি স্পষ্টভাবে জিজ্ঞাসা করতে পারে, তাই কম্পিউটারটি উপস্থিত xথাকলেও পেতে পারে y

এটি কি স্ট্যাকের অবস্থানটি কেবলমাত্র ভেরিয়েবলের আজীবন / সুযোগ সম্পর্কে এবং পুরো স্ট্যাকটি আসলে সমস্ত সময় প্রোগ্রামে অ্যাক্সেসযোগ্য?

হ্যাঁ. আপনি যখন কোনও ফাংশন থেকে প্রস্থান করবেন, তখন স্ট্যাক পয়েন্টারটি তার আগের অবস্থানে ফিরে আসে, কার্যকরভাবে মোছা হয় xএবং y, তবে প্রযুক্তিগতভাবে মেমরিটি অন্য কোনও কিছুর জন্য ব্যবহার না করা অবধি তারা সেখানে থাকবে। অতিরিক্তভাবে, যদি আপনার ফাংশনটি অন্য কোনও ফাংশন কল করে xএবং yএখনও উপস্থিত থাকবে এবং স্ট্যাকের মধ্যে খুব বেশি নিচে যাওয়ার দ্বারা অ্যাক্সেস করা যেতে পারে।


1
ওপি টেবিলে নিয়ে আসে এমন ব্যাকগ্রাউন্ড জ্ঞানের বাইরে কথা না বলার ক্ষেত্রে এটি এখন পর্যন্ত সবচেয়ে পরিষ্কার উত্তর বলে মনে হচ্ছে। সত্যিই ওপি লক্ষ্যবস্তু করার জন্য +1!
বেন আই।

1
আমিও রাজি! যদিও সমস্ত উত্তরগুলি অত্যন্ত সহায়ক এবং আমি অত্যন্ত কৃতজ্ঞ, আমার মূল পোস্টটি অনুপ্রাণিত হয়েছিল কারণ আমি বুঝতে পারি যে (ডি) মান / রেফারেন্সের ধরণের পার্থক্য কীভাবে ঘটে তা বোঝার জন্য এই পুরো স্ট্যাক / গাদা জিনিসটি একেবারে মৌলিক, তবে আমি পারিনি ' আপনি যদি কেবল "স্ট্যাক" এর শীর্ষটি দেখতে পারেন তবে কীভাবে তা দেখুন। সুতরাং আপনার উত্তর আমাকে সে থেকে মুক্তি দেয়। (আমি প্রথম অনুভূতিটি পেয়েছিলাম যখন আমি প্রথম বুঝতে পারি যে পদার্থবিজ্ঞানের সমস্ত বিপরীত স্কোয়ার আইনগুলি কেবল একটি গোলক থেকে বেরিয়ে আসা রেডিয়েশনের জ্যামিতির বাইরে পড়ে এবং আপনি এটি দেখতে একটি সাধারণ চিত্র আঁকতে পারেন))
সেলিন অ্যাটউড

আমি এটি ভালবাসি কারণ এটি সর্বদা প্রচুর পরিমাণে সহায়ক যখন আপনি দেখতে পান যে কীভাবে এবং কেন উচ্চ স্তরের কিছু ঘটনা (উদাহরণস্বরূপ ভাষায়) সত্যিই বিমূর্ত গাছের নিচে আরও কিছু মৌলিক ঘটনার কারণে। এমনকি যদি এটি রাখা হয় বেশ সহজ।
সেলিন অ্যাটউড

1
@ ক্যালেনা অ্যাটউড দয়া করে নোট করুন যে ভেরিয়েবলগুলি স্ট্যাক থেকে সরিয়ে নেওয়ার পরে "বল দ্বারা" অ্যাক্সেস করার চেষ্টা আপনাকে অনিশ্চিত / অপরিজ্ঞাত আচরণ দেয় এবং করা উচিত নয় should লক্ষ্য করুন আমি বলিনি "বিটি" বি / সি কিছু ভাষা আপনাকে এটি ব্যবহার করার অনুমতি দেবে। তবুও, এটি একটি প্রোগ্রামিং ভুল হতে পারে এবং এড়ানো উচিত।
কোড_ড্রেড

12

কোনও সংকলক কীভাবে স্ট্যাক পরিচালনা করে এবং স্ট্যাকের মানগুলি কীভাবে অ্যাক্সেস করা হয় তার একটি নিখুঁত উদাহরণ প্রদান করতে আমরা GCCলক্ষ্য আর্কিটেকচার হিসাবে i386 সহ একটি লিনাক্স পরিবেশে তৈরি ভিজ্যুয়াল চিত্রগুলি, এবং আরও কোড দেখতে পারি ।

1. স্ট্যাক ফ্রেম

আপনারা জানেন যে স্ট্যাকটি একটি চলমান প্রক্রিয়ার ঠিকানা জায়গার একটি অবস্থান যা ফাংশন , বা পদ্ধতি দ্বারা ব্যবহৃত হয় সেই অর্থে যে স্থানীয়ভাবে ঘোষিত ভেরিয়েবলগুলির জন্য স্ট্যাকের উপর স্থান বরাদ্দ করা হয়েছে, পাশাপাশি ফাংশনে পাস হওয়া আর্গুমেন্ট ( কোনও ফাংশনের বাইরে ঘোষিত ভেরিয়েবলের জন্য স্থান (অর্থাত্ গ্লোবাল ভেরিয়েবলগুলি) ভার্চুয়াল মেমোরিতে আলাদা অঞ্চলে বরাদ্দ করা হয়)। একটি ফাংশন এর সমস্ত ডেটার জন্য বরাদ্দ স্থান একটি স্ট্যাক ফ্রেম উল্লেখ করা হয় । এখানে একাধিক স্ট্যাক ফ্রেমের একটি ভিজ্যুয়াল চিত্রায়ন রয়েছে ( কম্পিউটার সিস্টেম থেকে : একটি প্রোগ্রামারের দৃষ্টিভঙ্গি ):

CSAPP স্ট্যাক ফ্রেম

2. স্ট্যাক ফ্রেম পরিচালনা এবং পরিবর্তনশীল অবস্থান

একটি নির্দিষ্ট স্ট্যাক ফ্রেমের মধ্যে স্ট্যাকের কাছে রচিত মানগুলি সংকলক দ্বারা পরিচালিত এবং প্রোগ্রাম দ্বারা পড়ার জন্য, এই মানগুলির অবস্থানগুলি গণনা করার জন্য এবং তাদের স্মৃতির ঠিকানা পুনরুদ্ধার করার জন্য কিছু পদ্ধতি থাকতে হবে। সিপিইউতে নিবন্ধগুলি স্ট্যাক পয়েন্টার হিসাবে উল্লেখ করা হয় এবং এটির সাথে বেস পয়েন্টার সহায়তা।

ebpকনভেনশন অনুসারে বেস পয়েন্টারটিতে স্ট্যাকের নীচে বা বেসের মেমরি ঠিকানা থাকে। স্ট্যাক ফ্রেমের মধ্যে সমস্ত মানগুলির অবস্থানগুলি একটি রেফারেন্স হিসাবে বেস পয়েন্টারে ঠিকানা ব্যবহার করে গণনা করা যেতে পারে। উপরের ছবিতে এটি চিত্রিত হয়েছে: %ebp + 4উদাহরণস্বরূপ বেস পয়েন্টার প্লাস 4-এ সঞ্চিত মেমরি ঠিকানা।

৩. সংকলক-উত্পন্ন কোড

তবে আমি যা পাই না তা হ'ল স্ট্যাকের চলকগুলি কীভাবে কোনও অ্যাপ্লিকেশন দ্বারা পড়তে হয় - যদি আমি এক্সটিকে একটি পূর্ণসংখ্যা হিসাবে ঘোষণা করি এবং নির্ধারণ করি তবে x = 3 বলুন এবং স্ট্যাকের উপর স্টোরেজ সংরক্ষিত থাকে এবং তার পরে 3 এর মান সংরক্ষণ করা হয় সেখানে, এবং তারপরে একই ফাংশনে আমি y হিসাবে ঘোষনা করব এবং নির্ধারণ করব, 4 বলুন, এবং তারপরে আমি অন্য এক্সপ্রেশনে এক্স ব্যবহার করব, (z = 5 + x বলুন) প্রোগ্রামটি কীভাবে z এর মূল্যায়ন করার জন্য এক্স পড়তে পারে এটা স্ট্যাকের y এর নীচে?

আসুন সিটিতে লিখিত একটি সাধারণ উদাহরণ প্রোগ্রামটি ব্যবহার করুন এটি কীভাবে কাজ করে তা দেখতে:

int main(void)
{
        int x = 3;
        int y = 4;
        int z = 5 + x;

        return 0;
}

আসুন আমরা এই সি উত্স পাঠ্যের জন্য জিসিসি দ্বারা উত্পাদিত সমাবেশ পাঠ্য পরীক্ষা করে দেখি (স্পষ্টতার জন্য আমি এটি কিছুটা সাফ করেছি):

main:
    pushl   %ebp              # save previous frame's base address on stack
    movl    %esp, %ebp        # use current address of stack pointer as new frame base address
    subl    $16, %esp         # allocate 16 bytes of space on stack for function data
    movl    $3, -12(%ebp)     # variable x at address %ebp - 12
    movl    $4, -8(%ebp)      # variable y at address %ebp - 8
    movl    -12(%ebp), %eax   # write x to register %eax
    addl    $5, %eax          # x + 5 = 9
    movl    %eax, -4(%ebp)    # write 9 to address %ebp - 4 - this is z
    movl    $0, %eax
    leave

আমরা কি মান্য যে ভেরিয়েবল, এক্স Y ও z ঠিকানাগুলি এ অবস্থিত হয় %ebp - 12, %ebp -8এবং %ebp - 4যথাক্রমে। অন্য কথায়, স্ট্যাক ফ্রেমের মধ্যে ভেরিয়েবলের অবস্থানগুলি main()সিপিইউ রেজিস্টারে সংরক্ষিত মেমরি ঠিকানা ব্যবহার করে গণনা করা হয় %ebp

৪. স্ট্যাক পয়েন্টারের বাইরে মেমরির ডেটা সুযোগের বাইরে

আমি স্পষ্টত কিছু মিস করছি। এটি কি স্ট্যাকের অবস্থানটি কেবলমাত্র ভেরিয়েবলের আজীবন / সুযোগ সম্পর্কে এবং পুরো স্ট্যাকটি আসলে সমস্ত সময় প্রোগ্রামে অ্যাক্সেসযোগ্য? যদি তা হয় তবে এর অর্থ কি আরও কিছু সূচক রয়েছে যা মানগুলি পুনরুদ্ধার করার জন্য স্ট্যাকের কেবলমাত্র ভেরিয়েবলের ঠিকানাগুলি ধারণ করে? তবে আমি ভেবেছিলাম স্ট্যাকের পুরো বিন্দুটি হ'ল মানগুলি ভেরিয়েবল ঠিকানার মতো একই জায়গায় সংরক্ষণ করা হয়েছিল?

স্ট্যাক ভার্চুয়াল মেমরির একটি অঞ্চল, যার ব্যবহারটি সংকলক দ্বারা পরিচালিত হয়। সংকলকটি এমনভাবে কোড উত্পন্ন করে যে স্ট্যাক পয়েন্টার (স্ট্যাকের শীর্ষের বাইরে মানগুলি) এর বাইরে মানগুলি কখনই রেফারেন্স হয় না। যখন কোনও ফাংশন বলা হয়, তখন স্ট্যাক পয়েন্টারের অবস্থান পরিবর্তন করে স্ট্যাকের স্থান তৈরি করে "সীমানা ছাড়াই" না বলে মনে করা হয়।

ফাংশনগুলি বলা হয় এবং ফিরে আসে, স্ট্যাক পয়েন্টার হ্রাস এবং বর্ধিত হয়। স্ট্যাকের কাছে লিখিত ডেটা সুযোগের বাইরে চলে যাওয়ার পরে অদৃশ্য হয়ে যায় না, তবে সংকলক এই ডেটাটি উল্লেখ করে নির্দেশনা উত্পন্ন করে না কারণ সংকলকটির জন্য %ebpবা ব্যবহার করে এই ডেটার ঠিকানাগুলি গণনা করার কোনও উপায় নেই %esp

5. সংক্ষিপ্তসার

সিপিইউ দ্বারা সরাসরি সম্পাদন করা যায় এমন কোডটি সংকলক তৈরি করে। সংকলক ফাংশন এবং সিপিইউ রেজিস্টারগুলির জন্য স্ট্যাক, স্ট্যাক ফ্রেমগুলি পরিচালনা করে। আইসি 386 আর্কিটেকচারে এক্সিকিউট করার উদ্দেশ্যে কোডটিতে স্ট্যাক ফ্রেমের ভেরিয়েবলের অবস্থানগুলি ট্র্যাক করতে জিসিসি দ্বারা ব্যবহৃত একটি কৌশল হ'ল স্ট্যাক ফ্রেম বেস পয়েন্টারে মেমরি ঠিকানা ব্যবহার করা, স্ট্যাক ফ্রেমের স্থানে %ebpভেরিয়েবলের মান লিখতে হবে as ঠিকানাতে অফসেটে %ebp


আমার যদি আমি জিজ্ঞাসা করি যে ছবিটি কোথা থেকে এসেছে? এটি সন্দেহজনকভাবে পরিচিত দেখাচ্ছে ... :-) এটি কোনও অতীত পাঠ্যপুস্তকে থাকতে পারে।
গ্রেট ডাক

1
nvmd। আমি স্রেফ লিঙ্কটি দেখেছি। আমি যা ভেবেছিলাম তা ছিল। বইটি ভাগ করে নেওয়ার জন্য +1।
গ্রেট হাঁস


9

দুটি বিশেষ রেজিস্টার রয়েছে: ইএসপি (স্ট্যাক পয়েন্টার) এবং ইবিপি (বেস পয়েন্টার)। যখন কোনও প্রক্রিয়া শুরু হয় প্রথম দুটি অপারেশন সাধারণত হয়

push        ebp  
mov         ebp,esp 

প্রথম অপারেশন স্ট্যাকের EBP এর মান সংরক্ষণ করে এবং দ্বিতীয় অপারেশন স্ট্যাক পয়েন্টারের মান বেস পয়েন্টারে (স্থানীয় ভেরিয়েবলগুলি অ্যাক্সেস করতে) লোড করে। সুতরাং, ইবিপি ইএসপি হিসাবে একই অবস্থানের দিকে নির্দেশ করে।

এসেমব্লার ভেরিয়েবলের নামগুলি ইবিপি অফসেটগুলিতে অনুবাদ করে। উদাহরণস্বরূপ, আপনার যদি দুটি স্থানীয় ভেরিয়েবল থাকে x,yএবং আপনার মতো কিছু থাকে

  x = 1;
  y = 2;
  return x + y;

তাহলে এটির মতো অনুবাদ করা যেতে পারে

   push        ebp  
   mov         ebp,esp
   mov  DWORD PTR [ ebp + 6],  1   ;x = 1
   mov  DWORD PTR [ ebp + 14], 2   ;y = 2
   mov  eax, [ ebp + 6 ]
   add  [ ebp + 14 ], eax          ; x + y 
   mov  eax, [ ebp + 14 ] 
   ...  

অফসেট মান 6 এবং 14 সংকলন সময়ে গণনা করা হয়।

মোটামুটি এটি কীভাবে কাজ করে তা। বিশদ জন্য একটি সংকলক বই পড়ুন।


14
এটি ইন্টেল x86 এর সাথে নির্দিষ্ট। এআরএম-তে, নিবন্ধভুক্ত এসপি (আর 13) পাশাপাশি এফপি (আর 11) ব্যবহার করা হয়। এবং x86-এ, নিবন্ধকের অভাবের অর্থ হ'ল আগ্রাসী সংকলকরা ইবিপি ব্যবহার করবে না কারণ এটি ইএসপি থেকে প্রাপ্ত হতে পারে। এটি তার শেষ উদাহরণটি স্পষ্ট, যেখানে সমস্ত EBP- সম্পর্কিত সম্বোধনটি ESP- সম্পর্কিততে অনুবাদ করা যেতে পারে, অন্য কোনও পরিবর্তনের প্রয়োজন নেই।
MSalters

আপনি কি প্রথমে x, y এর জন্য জায়গা তৈরির জন্য ESP এ একটি এসবিউবি মিস করছেন না?
হেগেন ভন ইটজেন

@ হ্যাজনভোন ইটজেন, সম্ভবত আমি কেবল ধারণাটি প্রকাশ করতে চেয়েছিলাম যে স্ট্যাকের মধ্যে বরাদ্দকৃত ভেরিয়েবলগুলি কীভাবে হার্ডওয়্যার রেজিস্টারগুলি ব্যবহার করে অ্যাক্সেস করা যায়।
fade2black

ডাউনভোটার্স, কমেন্টস দয়া করে !!!
fade2black

8

আপনি কি বিভ্রান্ত? কারণ স্থানীয় স্ট্যাকের মধ্যে সংরক্ষিত ভেরিয়েবল স্ট্যাক অ্যাক্সেস নিয়ম অ্যাক্সেস নয়: বা শুধু প্রথম সর্বশেষ আউট, Filo

জিনিসটি হ'ল FILO বিধি স্থানীয় ভেরিয়েবলের পরিবর্তে ফাংশন কল সিক্যুয়েন্স এবং স্ট্যাক ফ্রেমের ক্ষেত্রে প্রযোজ্য ।

স্ট্যাক ফ্রেম কী?

আপনি যখন কোনও ফাংশন প্রবেশ করেন, এটি স্ট্যাকের কিছু পরিমাণ মেমরি দেওয়া হয়, তাকে স্ট্যাক ফ্রেম বলে। ফাংশনের স্থানীয় ভেরিয়েবলগুলি স্ট্যাক ফ্রেমে সংরক্ষণ করা হয়। আপনি কল্পনা করতে পারেন যে স্ট্যাক ফ্রেমের আকারের ফাংশন থেকে ফাংশন পরিবর্তিত হয় কারণ প্রতিটি ফাংশনের বিভিন্ন সংখ্যা এবং স্থানীয় ভেরিয়েবলের আকার রয়েছে।

স্থানীয় ভেরিয়েবলগুলি স্ট্যাক ফ্রেমে কীভাবে সংরক্ষণ করা হয় তা ফিলোর সাথে কোনও সম্পর্ক নেই। (এমনকি আপনার উত্স কোডে আপনার স্থানীয় ভেরিয়েবলের উপস্থিতির ক্রমও নিশ্চিত করে না যে স্থানীয় ভেরিয়েবলগুলি সেই ক্রমে সংরক্ষণ করা হবে)) আপনি আপনার প্রশ্নে যথাযথভাবে অনুমিত হয়েছিলেন, "অন্য কিছু সূচি রয়েছে যা কেবলমাত্র ভেরিয়েবলের ঠিকানাগুলি ধারণ করে holds মানগুলি পুনরুদ্ধার করার জন্য স্ট্যাকে "। স্থানীয় ভেরিয়েবলের ঠিকানাগুলি সাধারণত বেস ঠিকানা দিয়ে গণনা করা হয় , যেমন স্ট্যাক ফ্রেমের সীমানা ঠিকানা এবং প্রতিটি স্থানীয় ভেরিয়েবলের জন্য নির্দিষ্ট অফসেটের মান

সুতরাং এই FILO আচরণ কখন প্রদর্শিত হবে?

এখন, আপনি অন্য ফাংশন কল করলে কি হবে? কলি ফাংশনটির নিজস্ব স্ট্যাক ফ্রেম থাকতে হবে এবং এটি এই স্ট্যাক ফ্রেমটি স্ট্যাকের মধ্যে ঠেলাঠেলি করা হয় । এটি হচ্ছে, কলি ফাংশনের স্ট্যাক ফ্রেমটি কলার ফাংশনের স্ট্যাক ফ্রেমের উপরে স্থাপন করা হয়। এবং যদি এই কলি ফাংশনটি অন্য ফাংশনকে কল করে, তবে তার স্ট্যাক ফ্রেমটিকে আবার স্ট্যাকের শীর্ষে চাপ দেওয়া হবে।

কোনও ফাংশন ফিরে আসলে কী হয়? যখন কোনও কলি ফাংশন কলার ফাংশনে ফিরে আসে, কলি ফাংশনটির স্ট্যাক ফ্রেমটি স্ট্যাক থেকে পপ আউট হয়ে যায়, ভবিষ্যতের ব্যবহারের জন্য স্থান মুক্ত করে।

সুতরাং আপনার প্রশ্ন থেকে:

এটি কি স্ট্যাকের অবস্থানটি কেবলমাত্র ভেরিয়েবলের আজীবন / সুযোগ সম্পর্কে এবং পুরো স্ট্যাকটি আসলে সমস্ত সময় প্রোগ্রামে অ্যাক্সেসযোগ্য?

আপনি এখানে বেশ সঠিক কারণ ফাংশন ফিরে আসার সময় স্ট্যাক ফ্রেমের স্থানীয় ভেরিয়েবল মানগুলি সত্যিই মোছা হয় না। মানটি কেবল সেখানেই থাকে, যদিও মেমরির অবস্থান যেখানে এটি সঞ্চিত থাকে তা কোনও ফাংশনের স্ট্যাক ফ্রেমের অন্তর্ভুক্ত নয়। মানটি মুছে ফেলা হয় যখন অন্য কোনও ফাংশন তার স্ট্যাক ফ্রেম অর্জন করে যার মধ্যে অবস্থানটি অন্তর্ভুক্ত থাকে এবং সেই মেমরির অবস্থানটিতে কিছু অন্যান্য মান লিখতে থাকে।

তাহলে স্তূপ থেকে স্ট্যাকের পার্থক্য কী?

স্ট্যাক এবং হিপ এই অর্থে একই যে তারা উভয় নাম যা মেমরির কিছু স্থানকে নির্দেশ করে। যেহেতু আমরা এর ঠিকানার সাথে মেমরির যে কোনও অবস্থান অ্যাক্সেস করতে পারি, তাই আপনি স্ট্যাক বা গাদা যে কোনও অবস্থান অ্যাক্সেস করতে পারেন।

পার্থক্যটি প্রতিশ্রুতি থেকে আসে যে কম্পিউটার সিস্টেম এটি কীভাবে ব্যবহার করবে সে সম্পর্কে করে। যেমনটি আপনি বলেছেন, গাদা রেফারেন্স টাইপের জন্য। যেহেতু গাদা মূল্যগুলির কোনও নির্দিষ্ট স্ট্যাক ফ্রেমের সাথে কোনও সম্পর্ক নেই, তাই মানটির পরিধিটি কোনও ফাংশনের সাথে আবদ্ধ নয়। স্থানীয় ভেরিয়েবলটি কোনও ফাংশনের মধ্যেই সজ্জিত হয় এবং আপনি বর্তমান ফাংশনের স্ট্যাক ফ্রেমের বাইরে অবস্থিত যে কোনও স্থানীয় ভেরিয়েবল মান অ্যাক্সেস করতে পারলেও সিস্টেমটি নিশ্চিত করে চেষ্টা করবে যে এই ধরণের আচরণটি ঘটবে না, ব্যবহার করে স্ট্যাক ফ্রেম এটি আমাদেরকে কিছু ধরণের বিভ্রম দেয় যা স্থানীয় পরিবর্তনশীল একটি নির্দিষ্ট ফাংশনে স্কোপ করা হয়।


4

একটি ভাষা রানটাইম সিস্টেম দ্বারা স্থানীয় ভেরিয়েবলগুলি প্রয়োগ করার বিভিন্ন উপায় রয়েছে। স্ট্যাক ব্যবহার করা একটি সাধারণ দক্ষ সমাধান, যা অনেক ব্যবহারিক ক্ষেত্রে ব্যবহৃত হয়।

স্বজ্ঞাতভাবে, স্ট্যাক পয়েন্টারটি spরানটাইমের সময় প্রায় রাখা হয় (একটি নির্দিষ্ট ঠিকানায়, বা একটি নিবন্ধে - এটি সত্যই গুরুত্বপূর্ণ)। ধরে নিন যে প্রতিটি "পুশ" স্ট্যাক পয়েন্টারটিকে বাড়িয়ে তোলে।

কম্পাইল সময়ে, কম্পাইলার প্রতিটি পরিবর্তনশীল এর ঠিকানা নির্ধারণ করে যেমন sp - Kযেখানে Kএকটি ধ্রুবক যা শুধুমাত্র পরিবর্তনশীল (অত: পর কম্পাইল সময়ে নির্ণিত করা যেতে পারে) পরিধি উপর নির্ভর করে।

নোট করুন যে আমরা এখানে "স্ট্যাক" শব্দটি স্বাচ্ছন্দ্যে ব্যবহার করছি। এই স্ট্যাকটি কেবল পুশ / পপ / শীর্ষ অপারেশনের মাধ্যমে অ্যাক্সেস করা যায় না, তবে এটি ব্যবহার করে অ্যাক্সেস করা যায় sp - K

উদাহরণস্বরূপ এই সিউডোকোডটি বিবেচনা করুন:

procedure f(int x, int y) {
  print(x,y);    // (1)
  if (...) {
    int z=x+y; // (2)
    print(x,y,z);  // (3)
  }
  print(x,y); // (4)
  return;
}

পদ্ধতিটি কল করা হলে, x,yস্ট্যাকের সাথে যুক্তিগুলি পাস করা যেতে পারে। সরলতার জন্য, ধরে নিন কনভেনশনটি হ'ল কলার xপ্রথমে ধাক্কা দেয় , তারপরে y

তারপরে, বিন্দুতে সংকলক (1) xsp - 2এবং yএ খুঁজে পেতে পারে sp - 1

বিন্দুতে (2), একটি নতুন পরিবর্তনশীল সুযোগে আনা হয়। সংকলকটি এমন কোড উত্পন্ন করে যা অঙ্ক করে x+y, অর্থাত কী দ্বারা নির্দেশিত sp - 2এবং sp - 1, এবং স্ট্যাকের যোগফলের ফলাফলকে ধাক্কা দেয়।

বিন্দু (3), zমুদ্রিত হয়। সংকলক জানে এটি সুযোগের সর্বশেষ পরিবর্তনশীল, তাই এটি দ্বারা নির্দেশিত sp - 1। পরিবর্তিত yহওয়ার পরে এটি আর নেই sp। তবুও, yসংকলকটি মুদ্রণ করতে জানে যে এটি এটি খুঁজে পেতে পারে, এই সুযোগে, এ sp - 2। একইভাবে, xএখন পাওয়া যায় sp - 3

বিন্দুতে (4), আমরা সুযোগটি প্রস্থান করি। zপপ করা হয়, এবং yআবার ঠিকানায় পাওয়া যায় sp - 1, এবং xহয় sp - 2

আমরা যখন ফিরে fআসি , হয় অথবা কলার x,yস্ট্যাক থেকে পপ হয়।

সুতরাং, সংকলকটির Kজন্য গণনা মোটামুটিভাবে কতগুলি ভেরিয়েবলের সুযোগে রয়েছে তা গণনা করার বিষয়। বাস্তব বিশ্বে এটি প্রকৃতপক্ষে আরও জটিল কারণ সমস্ত ভেরিয়েবলের আকার একই থাকে না, সুতরাং এর গণনা Kকিছুটা জটিল। কখনও কখনও, স্ট্যাকটিতে ফিরতি ঠিকানাও থাকে f, সুতরাং সেই সাথে Kঅবশ্যই "এড়িয়ে যান"। তবে এগুলি প্রযুক্তিগত বিষয়গুলি।

মনে রাখবেন, কিছু প্রোগ্রামিং ভাষায়, আরও জটিল বৈশিষ্ট্যগুলি পরিচালনা করতে হলে জিনিসগুলি আরও জটিল হয়ে উঠতে পারে। যেমন নেস্টেড পদ্ধতিগুলির জন্য খুব সাবধানী বিশ্লেষণ প্রয়োজন, যেহেতু Kএখন অনেক রিটার্নের ঠিকানাগুলি "এড়িয়ে যেতে" হবে, বিশেষত যদি নেস্টেড পদ্ধতিটি পুনরাবৃত্তি করে। বন্ধ / ল্যাম্বডাস / বেনামে ফাংশনগুলিতে "বন্দী" ভেরিয়েবলগুলি পরিচালনা করতে কিছু যত্ন প্রয়োজন। তবুও, উপরের উদাহরণটির মূল ধারণাটি বোঝানো উচিত illust


3

মেমরির ঠিকানার জন্য স্থির নাম হিসাবে ভেরিয়েবলগুলি ভাবা সবচেয়ে সহজ ধারণা । প্রকৃতপক্ষে, কিছু এসেমব্লাররা মেশিন কোডটি সেভাবে প্রদর্শন করে ("ঠিকানাতে স্টোরের মান 5 i", যেখানে iএকটি পরিবর্তনশীল নাম রয়েছে)।

এর মধ্যে কয়েকটি ঠিকানা বৈশ্বিক ভেরিয়েবলের মতো "পরম" হয়, কিছু স্থানীয় ভেরিয়েবলের মতো "আপেক্ষিক" হয়। ফাংশনগুলিতে ভেরিয়েবল (অর্থাত্ ঠিকানাগুলি) "স্ট্যাক" এর কোনও জায়গার সাথে সম্পর্কিত যা প্রতিটি ফাংশন আমন্ত্রণের জন্য পৃথক; এইভাবে একই নামটি বিভিন্ন প্রকৃত অবজেক্টগুলিকে উল্লেখ করতে পারে এবং একই ফাংশনের সার্কুলার কলগুলি স্বাধীন স্মৃতিতে কাজ করা স্বতন্ত্র প্রার্থনা।


2

স্ট্যাকের মধ্যে যেতে পারে এমন ডেটা আইটেমগুলিকে স্ট্যাক লাগিয়ে দেওয়া হয় - হ্যাঁ! এটি একটি প্রিমিয়াম স্পেস। এছাড়াও, একবার আমরা xস্ট্যাকের দিকে ঠেলে এবং তারপরে স্ট্যাকের দিকে ঠেলে yদিই, আদর্শভাবে আমরা সেখানে না আসা xপর্যন্ত অ্যাক্সেস করতে পারি না yyঅ্যাক্সেস করতে আমাদের পপ করতে হবে x। আপনি তাদের সঠিক পেয়েছেন।

স্ট্যাকটি ভেরিয়েবলের নয়, তবে এর frames

আপনি যেখানে ভুল পেয়েছেন তা হ'ল স্ট্যাকটি সম্পর্কে। স্ট্যাকে এটি ডেটা আইটেম নয় যা সরাসরি ধাক্কা দেয়। বরং, স্ট্যাকের উপরে কিছু stack-frameধাক্কা দেওয়া হয়। এই স্ট্যাক-ফ্রেমে ডেটা আইটেম রয়েছে । আপনি স্ট্যাকের গভীরতায় ফ্রেমগুলি অ্যাক্সেস করতে পারবেন না, আপনি উপরের ফ্রেম এবং এর মধ্যে থাকা সমস্ত ডেটা আইটেম অ্যাক্সেস করতে পারবেন।

আসুন আমরা আমাদের ডেটা আইটেম দুটি স্ট্যাক ফ্রেমে frame-xএবং বান্ডিল আছে frame-y। আমরা তাদের একের পর এক ধাক্কা দিয়েছি। এখন যতক্ষণ frame-yউপরে উপরে বসে থাকে frame-x, আপনি আদর্শভাবে কোনও ডেটা আইটেম ভিতরে প্রবেশ করতে পারবেন না frame-x। কেবল frame-yদৃশ্যমান। তবে frame-yএটি দৃশ্যমান, আপনি এতে থাকা সমস্ত ডেটা-আইটেম অ্যাক্সেস করতে পারবেন। পুরো ফ্রেমটির মধ্যে থাকা সমস্ত ডেটা আইটেম প্রকাশ করা দৃশ্যমান।

উত্তরের শেষ। এই ফ্রেমগুলিতে আরও (রেন্ট)

সংকলনের সময়, প্রোগ্রামের সমস্ত কার্যকারিতার একটি তালিকা তৈরি করা হয়। তারপরে প্রতিটি ফাংশনের জন্য স্ট্যাকেবল ডেটা আইটেমগুলির একটি তালিকা তৈরি করা হয়। তারপরে প্রতিটি ফাংশনের জন্য একটি stack-frame-templateতৈরি করা হয়। এই টেমপ্লেটটি একটি ডাটা স্ট্রাকচার যা ঐ সমস্ত মনোনীত ভেরিয়েবল, ফাংশন এর ইনপুট ডেটার জন্য স্থান, আউটপুট তথ্য ইত্যাদি এখন রানটাইম, যখনই একটি ফাংশন বলা হয় সময় রয়েছে, এই একটি কপি templateসমস্ত ইনপুট এবং অন্তর্বর্তী ভেরিয়েবল সহ - স্ট্যাক রাখা হয় । যখন এই ফাংশনটি অন্য কোনও ফাংশনকে কল করে, তখন সেই ফাংশনটির একটি নতুন কপি stack-frameস্ট্যাকের উপরে রাখা হয়। এখন যতদিন যে ফাংশন চলছে, এই ফাংশন ডেটা আইটেম সংরক্ষিত আছে। এই ফাংশনটি শেষ হয়ে গেলে , এর স্ট্যাক-ফ্রেমটি পপআপ হয়ে যায়। এখনএই স্ট্যাক-ফ্রেমটি সক্রিয় এবং এই ফাংশনটি তার সমস্ত ভেরিয়েবল অ্যাক্সেস করতে পারে।

মনে রাখবেন যে স্ট্যাক-ফ্রেমের গঠন এবং গঠন প্রোগ্রামিং ভাষা থেকে প্রোগ্রামিং ভাষাতে পরিবর্তিত হয়। এমনকি একটি ভাষার মধ্যেও বিভিন্ন বাস্তবায়নে সূক্ষ্ম পার্থক্য থাকতে পারে।


সিএস বিবেচনা করার জন্য আপনাকে ধন্যবাদ। আমি এখন একজন প্রোগ্রামার, পিয়ানো পাঠ গ্রহণের একদিন :)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.