আমরা এখনও পিছনে পিছনে স্ট্যাক বৃদ্ধি?


46

সি কোডটি সংকলন করে এবং অ্যাসেমব্লিকে দেখার সময়, এটি সমস্ত স্ট্যাকটি এভাবে পিছন দিকে বাড়তে থাকে:

_main:
    pushq   %rbp
    movl    $5, -4(%rbp)
     popq    %rbp
    ret

-4(%rbp)- এর অর্থ কি বেস পয়েন্টার বা স্ট্যাক পয়েন্টারটি আসলে উপরে যাওয়ার পরিবর্তে মেমরি ঠিকানাগুলি নীচে নিয়ে যাচ্ছে? তা কেন?

আমি পরিবর্তন $5, -4(%rbp)করতে $5, +4(%rbp)সংকলন এবং কোড দৌড়ে এবং কোন ত্রুটি রয়েছে। তাহলে কেন আমাদের এখনও মেমরি স্ট্যাকের পিছনে যেতে হবে?


2
নোট করুন যে -4(%rbp)বেস পয়েন্টারটি মোটেও সরায় +4(%rbp)না এবং সম্ভবত এটি কাজ করতে পারে না।
মার্গারেট ব্লুম

14
" কেন আমাদের এখনও পিছনে যেতে হবে " - আপনার কি মনে হয় এগিয়ে যাওয়ার সুবিধা হবে? শেষ পর্যন্ত, এটি কোনও ব্যাপার নয়, আপনাকে কেবল একটি বেছে নিতে হবে।
বার্গি

31
"কেন আমরা পিছনে পিছনে স্ট্যাক বৃদ্ধি?" - কারণ আমরা যদি অন্য কেউ না জিজ্ঞাসা malloc
করতাম

2
@ মার্গারেটব্লুম: স্পষ্টতই ওপি-র প্ল্যাটফর্মে, সিআরটি স্টার্টআপ কোডটি mainক্লোবার যদি তার আরবিপি করে তবে তা বিবেচনা করে না । এটা অবশ্যই সম্ভব। (এবং হ্যাঁ, লেখাটি 4(%rbp)সংরক্ষিত আরবিপি মানকে বাড়িয়ে তুলবে)। এরর আসলে, এই মেইনটি কখনই করে না mov %rsp, %rbp, তাই মেমরি অ্যাক্সেসটি কলারের আরবিপির সাথে তুলনামূলক , যদি ওপি আসলে এটিই পরীক্ষিত হয় !!! এটি যদি সত্যই সংকলক আউটপুট থেকে অনুলিপি করা হয়, কিছু নির্দেশাবলীর বাইরে ছিল!
পিটার কর্ডেস

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

উত্তর:


86

এর অর্থ কি বেস পয়েন্টার বা স্ট্যাক পয়েন্টারটি আসলে উপরে যাওয়ার পরিবর্তে মেমরিের ঠিকানাগুলি নীচে নিয়ে যাচ্ছে? তা কেন?

হ্যাঁ, pushনির্দেশাবলী স্ট্যাক পয়েন্টার হ্রাস করে এবং স্ট্যাকটিতে লিখুন, যখন popবিপরীত করুন, স্ট্যাক থেকে পড়ুন এবং স্ট্যাক পয়েন্টারটি বৃদ্ধি করুন।

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

যদি স্ট্যাক এবং হিপ উভয়ই একই দিকে বৃদ্ধি পায় তবে দুটি ফাঁক রয়েছে এবং স্ট্যাকটি সত্যিই স্তূপের ফাঁকায় বাড়তে পারে না (বিপরীতে এছাড়াও সমস্যাযুক্ত)।

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

কেউ তর্ক করতে পারে যে 64৪-বিট মেশিনে একাধিক ফাঁক দেওয়ার অনুমতি দেওয়ার জন্য পর্যাপ্ত ঠিকানা স্থান রয়েছে - এবং প্রমাণ হিসাবে, যখন কোনও প্রক্রিয়াতে একাধিক থ্রেড থাকে তখন একাধিক ফাঁকগুলি অবশ্যই ঘটে থাকে। যদিও চারপাশের জিনিসগুলিকে পরিবর্তন করার পক্ষে এটি যথেষ্ট অনুপ্রেরণা নয়, যেহেতু একাধিক ব্যবধান সিস্টেমের সাথে বর্ধনের দিকটি তর্কসাপেক্ষভাবে স্বেচ্ছাসেবী, সুতরাং traditionতিহ্য / সামঞ্জস্যতা স্কেলকে পরামর্শ দেয়।


আপনি যাতে স্ট্যাকের দিক পরিবর্তন, বা অন্য নিবেদিত ঠেলাঠেলি & পপিং নির্দেশাবলী (যেমন ব্যবহারের উপর ছেড়ে দিতে হবে হবে CPU- র স্ট্যাকের হ্যান্ডলিং নির্দেশাবলী পরিবর্তন করতে হবে চাই push, pop, call, ret, অন্যদের)।

নোট করুন যে এমআইপিএস নির্দেশ সেট আর্কিটেকচারটি ডেডিকেটেড push& নেই pop, সুতরাং উভয় দিকেই স্ট্যাকটি বৃদ্ধি করা ব্যবহারিক - আপনি এখনও একটি থ্রেড প্রক্রিয়াটির জন্য একটি ফাঁক মেমরি লেআউট চাইতে পারেন, তবে স্ট্যাকটি উপরের দিকে এবং গাদাটি বাড়িয়ে তুলতে পারেন নীচের দিকে। আপনি যদি এটি করেন তবে, কিছু সি ভ্যারাগস কোডের উত্স বা হুডের নীচে প্যারামিটার পাসিংয়ের ক্ষেত্রে সামঞ্জস্যতার প্রয়োজন হতে পারে।

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


32
এটা ঠিক নয় pushএবং popঅধিকাংশ আর্কিটেকচারের উপর, বরং অনেক বেশী গুরুত্বপূর্ণ বিঘ্ন-হ্যান্ডলিং, call, ret, এবং অন্য যাই হোক না কেন বেকড-ইন স্ট্যাক সাথে পারস্পরিক হয়েছে।
Deduplicator

3
এআরএমের চারটি স্ট্যাক স্বাদ থাকতে পারে।
মার্গারেট ব্লুম

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

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

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

8

আপনার নির্দিষ্ট সিস্টেমে স্ট্যাকটি উচ্চ মেমোরি ঠিকানা থেকে শুরু হয় এবং "স্মৃতিতে" নীচের দিকে কম মেমোরি ঠিকানাগুলিতে শুরু হয়। (কম থেকে উচ্চ পর্যন্ত প্রতিসম ক্ষেত্রেও বিদ্যমান)

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


1

বরাদ্দ এবং অপরিবর্তিত স্ট্যাক মেমরির মধ্যে সীমানায় স্ট্যাক পয়েন্টার পয়েন্টার। এটিকে নীচের দিকে বাড়ানোর অর্থ হ'ল এটি বরাদ্দ স্ট্যাকের জায়গাতে প্রথম কাঠামোর শুরুতে এবং অন্যান্য বরাদ্দ আইটেমগুলি আরও বড় ঠিকানাগুলিতে অনুসরণ করে points বরাদ্দ কাঠামোর শুরুতে পয়েন্টার পয়েন্ট থাকা অন্য রাউন্ডের চেয়ে অনেক বেশি সাধারণ।

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

নোট করুন যে স্ট্যাক ফ্রেম এবং তাদের সূচীকরণটি কম্পিউটারের সংকলিত ভাষার একটি দিক, সুতরাং এটি সংকলকের কোড জেনারেটর যা একটি দুর্বল সমাবেশ ভাষা প্রোগ্রামারের পরিবর্তে "অপ্রাকৃতিকতা" মোকাবেলা করতে হবে।

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


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