1) সংকলিত বাইনারি প্রম / ফ্ল্যাশ হ্যাঁ লিখিত হয়। ইউএসবি, সিরিয়াল, আই 2 সি, জেট্যাগ ইত্যাদি ডিভাইসের উপর নির্ভর করে যে ডিভাইসটি সমর্থন করে তা বুট প্রক্রিয়াটি বোঝার জন্য অপ্রয়োজনীয়।
2) এটি সাধারণত কোনও মাইক্রোকন্ট্রোলারের ক্ষেত্রে সত্য নয়, প্রাথমিক ব্যবহারের ক্ষেত্রে র্যাম / ফ্ল্যাশ এবং র্যামে ডেটা থাকতে হবে। আর্কিটেকচার যাই হোক না কেন। নন-মাইক্রোকন্ট্রোলার, আপনার পিসি, আপনার ল্যাপটপ, আপনার সার্ভারের জন্য প্রোগ্রামটি নন-ভোল্টাইল (ডিস্ক) থেকে রামে অনুলিপি করা হয় তারপর সেখান থেকে চালানো হবে। কিছু মাইক্রোকন্ট্রোলার আপনাকে র্যামও ব্যবহার করতে দেয়, এমনকি যেগুলি হার্ভার্ড দাবি করে এমনকি এটি সংজ্ঞা লঙ্ঘন করে বলে মনে হয়। হার্ভার্ড সম্পর্কে কিছুই নেই যা আপনাকে দিকনির্দেশের দিকে ম্যাম ম্যাপিং থেকে বিরত রাখে, ক্ষমতা শেষ হওয়ার পরে আপনাকে নির্দেশাবলী পাওয়ার জন্য কেবল একটি ব্যবস্থা থাকা দরকার (যা সংজ্ঞা লঙ্ঘন করে, তবে হার্ভার্ড সিস্টেমগুলি অন্য কার্যকর হওয়ার জন্য এটি করতে হবে) মাইক্রোকন্ট্রোলার হিসাবে)।
3) সাজানো।
প্রতিটি সিপিইউ একটি ডিজিস্টিনিস্টিক হিসাবে "বুট" করে, যেমন নকশা করা হয়। সর্বাধিক সাধারণ উপায় একটি ভেক্টর টেবিল যেখানে পাওয়ার আপ হওয়ার পরে চালানোর জন্য প্রথম নির্দেশাবলীর ঠিকানাটি রিসেট ভেক্টরে রয়েছে, হার্ডওয়্যার পরে যে ঠিকানাটি পড়ে তা চালানো শুরু করার জন্য সেই ঠিকানাটি ব্যবহার করে। অন্য সাধারণ উপায়টি হ'ল প্রসেসরটি কোনও সুপরিচিত ঠিকানায় ভেক্টর টেবিল ছাড়া চালানো শুরু করে। কখনও কখনও চিপে "স্ট্র্যাপস" থাকে, এমন কিছু পিন থাকে যা রিসেট প্রকাশের আগে আপনি উচ্চ বা নিম্নটি বেঁধে রাখতে পারেন, যুক্তিটি বিভিন্ন উপায়ে বুট করার জন্য ব্যবহার করে। আপনাকে সিপিইউ পৃথক করতে হবে, প্রসেসরের কোরটি সিস্টেমের বাকি অংশ থেকে। সিপিইউ কীভাবে পরিচালিত হয় তা বুঝুন এবং তারপরে বুঝতে পারবেন যে চিপ / সিস্টেম ডিজাইনারদের সিপিইউর বাইরের চারপাশে সেটআপ ঠিকানা ডিকোডার রয়েছে যাতে সিপাস ঠিকানা জায়গার কিছু অংশ একটি ফ্ল্যাশ দিয়ে যোগাযোগ করে, এবং কিছুটি ভেড়ার সাথে এবং কিছু পেরিফেরাল (uart, i2c, spi, gpio, ইত্যাদি) সহ। আপনি চাইলে সেই একই সিপিইউ কোরটি নিতে পারেন এবং এটিকে অন্যভাবে মোড়ানো করতে পারেন। আপনি যখন বাহু বা মাইপস ভিত্তিক কিছু কিনবেন তখন আপনি এটি পাবেন। আর্ম এবং মিপস সিপু কোর তৈরি করে, যা চিপ লোকেরা তাদের নিজস্ব জিনিসপত্র চারপাশে কেনে এবং জড়িয়ে রাখে, বিভিন্ন কারণে তারা সেই জিনিসটিকে ব্র্যান্ড থেকে ব্র্যান্ডের সাথে সামঞ্জস্যপূর্ণ করে না। মূল কারণের বাইরে যখন কিছু আসে তখন খুব কমই জেনেরিক আর্ম প্রশ্ন করতে পারে।
একটি মাইক্রোকন্ট্রোলার একটি চিপে একটি সিস্টেম হওয়ার চেষ্টা করে, তাই এর নন-অস্থির মেমরি (ফ্ল্যাশ / রোম), উদ্বায়ী (শ্রম) এবং সিপিইউ পেরিফেরিয়ালের মিশ্রণের পাশাপাশি একই চিপে থাকে। তবে চিপটি অভ্যন্তরীণভাবে এমনভাবে ডিজাইন করা হয়েছে যে ফ্ল্যাশটি সিপিইউর ঠিকানা স্পেসে ম্যাপ করা থাকে যা সেই সিপিইউর বুটের বৈশিষ্ট্যের সাথে মেলে। উদাহরণস্বরূপ, যদি সিপিইউতে 0xFFFC ঠিকানায় একটি রিসেট ভেক্টর থাকে, তবে দরকারী প্রোগ্রামগুলির জন্য ঠিকানার জায়গাতে পর্যাপ্ত ফ্ল্যাশ / রোমের পাশাপাশি ফ্ল্যাশ / রোম থাকা দরকার যা সেই ঠিকানার প্রতিক্রিয়া জানায় 1 এই প্রয়োজনীয়তাগুলি পূরণ করতে একটি চিপ ডিজাইনার 0xF000 থেকে শুরু করে 0x1000 বাইট বেছে নিতে পারেন। এবং সম্ভবত তারা একটি কম ঠিকানা বা সম্ভবত 0x0000, এবং মাঝখানে কোথাও পেরিফেরিয়াল কিছু পরিমাণ র্যাম লাগিয়েছে।
সিপিইউর আরেকটি স্থাপত্য সম্ভবত শূন্যের থেকে সম্পাদন শুরু করতে পারে, সুতরাং তাদের বিপরীতটি করা দরকার, ফ্ল্যাশটি স্থাপন করা উচিত যাতে এটি শূন্যের কাছাকাছি কোনও অ্যাড্রেস রেঞ্জের উত্তর দেয়। উদাহরণস্বরূপ 0x0000 থেকে 0x0FFF বলুন। এবং তারপরে কিছুটা ভেড়া রেখে দিন।
চিপ ডিজাইনাররা জানেন কীভাবে সিপিইউ বুট হয় এবং তারা সেখানে অ-উদ্বায়ী স্টোরেজ স্থাপন করে (ফ্ল্যাশ / রোম)। তারপরে সফ্টওয়্যার ভাবার লোকেরা সেই সিপিইউর সুপরিচিত আচরণের সাথে মেলে বুট কোডটি লিখতে পারে। আপনাকে রিসেট ভেক্টরটিতে রিসেট ভেক্টরের ঠিকানা এবং আপনার বুট কোডটি রিসেট ভেক্টরে সংজ্ঞায়িত ঠিকানায় রাখতে হবে। সরঞ্জামচেন এখানে আপনাকে ব্যাপক সাহায্য করতে পারে। কখনও কখনও, পয়েন্ট সহ ক্লিক করুন এবং আইডস বা অন্যান্য স্যান্ডবক্সগুলিতে ক্লিক করুন তারা আপনার জন্য সবচেয়ে বেশি কাজ করতে পারে আপনি যা করেন তা হ'ল উচ্চ স্তরের ভাষায় (সি) এপিআই কল করুন।
তবে, এটি করা হয়ে গেলে ফ্ল্যাশ / রোমে লোড হওয়া প্রোগ্রামটি সিপিইউর হার্ডওয়ার্ড বুট আচরণের সাথে মেলে। আপনার প্রোগ্রামের প্রধান অংশ () এর সি অংশ আগে এবং আপনি যদি আপনার প্রবেশ বিন্দু হিসাবে প্রধান ব্যবহার করেন তবে কিছু কাজ করতে হবে। এসি প্রোগ্রামার ধরে নেয় যে যখন প্রাথমিক মান সহ একটি ভেরিয়েবল ঘোষণা করে তখন তারা আশা করে যে এটি বাস্তবে কাজ করবে। ওয়েল, ভেরিয়েবলগুলি, কনস্টের চেয়ে ভিন্ন, রামে থাকে তবে আপনার যদি প্রাথমিক মান সহ একটি থাকে তবে প্রাথমিক মানটি অ-উদ্বায়ী র্যামে থাকতে হবে। সুতরাং এটি .ডাটা বিভাগ এবং সি বুটস্ট্র্যাপের ফ্ল্যাশ থেকে রামে ড্যাটা স্টাফ অনুলিপি করা প্রয়োজন (যেখানে সাধারণত সরঞ্জামচেইন আপনার জন্য নির্ধারিত হয়)। কোনও প্রাথমিক মান ছাড়াই আপনি যে গ্লোবাল ভেরিয়েবলগুলি ঘোষণা করেন তা আপনার প্রোগ্রামটি শুরুর আগে শূন্য বলে ধরে নেওয়া হয় যদিও আপনার সত্যিকার অর্থে এটি অনুমান করা উচিত নয় এবং কৃতজ্ঞতার সাথে কিছু সংকলক অবিচ্ছিন্ন ভেরিয়েবল সম্পর্কে সতর্ক করতে শুরু করেছেন। এটি .bss বিভাগ, এবং সি বুটস্ট্র্যাপ শূন্যগুলি যা মেষ হিসাবে প্রকাশিত হয়, সামগ্রী, শূন্যগুলি অ-উদ্বায়ী মেমরিতে সংরক্ষণ করতে হয় না, তবে সূচনা ঠিকানা এবং কতগুলি হয়। আবার টুলচেন আপনাকে এখানে ব্যাপক সাহায্য করে। এবং সর্বশেষে খালি ন্যূনতম আপনাকে স্ট্যাক পয়েন্টার সেটআপ করতে হবে কারণ সি প্রোগ্রামগুলি স্থানীয় ভেরিয়েবলগুলি রাখতে সক্ষম হবে এবং অন্যান্য ফাংশনগুলি কল করতে পারে expect তারপরে সম্ভবত অন্য কিছু চিপ নির্দিষ্ট জিনিস হয়ে গেছে, বা আমরা বাকী চিপ নির্দিষ্ট জিনিসগুলি সিতে ঘটতে দেব অ-উদ্বায়ী মেমরিতে সঞ্চয় করতে হবে না, তবে শুরু করার ঠিকানা এবং কতগুলি। আবার টুলচেন আপনাকে এখানে ব্যাপক সাহায্য করে। এবং সর্বশেষে খালি ন্যূনতম আপনাকে স্ট্যাক পয়েন্টার সেটআপ করতে হবে কারণ সি প্রোগ্রামগুলি স্থানীয় ভেরিয়েবলগুলি রাখতে সক্ষম হবে এবং অন্যান্য ফাংশনগুলি কল করতে পারে expect তারপরে সম্ভবত অন্য কিছু চিপ নির্দিষ্ট জিনিস হয়ে গেছে, বা আমরা বাকী চিপ নির্দিষ্ট জিনিসগুলি সিতে ঘটতে দেব অ-উদ্বায়ী মেমরিতে সঞ্চয় করতে হবে না, তবে শুরু করার ঠিকানা এবং কতগুলি। আবার টুলচেন আপনাকে এখানে ব্যাপক সাহায্য করে। এবং সর্বশেষে খালি ন্যূনতম আপনাকে স্ট্যাক পয়েন্টার সেটআপ করতে হবে কারণ সি প্রোগ্রামগুলি স্থানীয় ভেরিয়েবলগুলি রাখতে সক্ষম হবে এবং অন্যান্য ফাংশনগুলি কল করতে পারে expect তারপরে সম্ভবত অন্য কিছু চিপ নির্দিষ্ট জিনিস হয়ে গেছে, বা আমরা বাকী চিপ নির্দিষ্ট জিনিসগুলি সিতে ঘটতে দেব
আর্ম থেকে কর্টেক্স-এম সিরিজ কোরগুলি এটি আপনার জন্য কিছু করবে, স্ট্যাক পয়েন্টারটি ভেক্টর টেবিলের মধ্যে রয়েছে, রিসেটের পরে চালানো কোডটি চিহ্নিত করার জন্য একটি রিসেট ভেক্টর রয়েছে, যাতে আপনাকে যা করতে হবে তা বাদ দিয়ে অন্য ভেক্টর টেবিল তৈরি করতে (যা আপনি সাধারণত যেভাবেই asm ব্যবহার করেন) আপনি asm ছাড়াই খাঁটি সি যেতে পারেন। এখন আপনি আপনার .ডাটা অনুলিপি করতে পারবেন না বা আপনার .bss শূন্য হয়েছে তাই আপনি যদি কর্টেক্স-এম ভিত্তিক কোনও কিছুতে asm ছাড়াই চেষ্টা করতে চান তবে আপনাকে নিজেরাই এটি করতে হবে। বড় বৈশিষ্ট্যটি রিসেট ভেক্টর নয়, তবে ভ্যাক্টরগুলিকে বাধা দেয় যেখানে হার্ডওয়্যার অস্ত্রের প্রস্তাবিত সি কলিং কনভেনশন অনুসরণ করে এবং আপনার জন্য নিবন্ধগুলি সংরক্ষণ করে এবং সেই ভেক্টরের জন্য সঠিক রিটার্ন ব্যবহার করে, যাতে আপনাকে প্রতিটি হ্যান্ডলারের চারপাশে ডান অ্যাসেমটি আবৃত করতে না হয় ( বা আপনার লক্ষ্যটির জন্য সরঞ্জামচেইন এটি আপনার জন্য জড়ানোর জন্য নির্দিষ্ট কৌশল রয়েছে specific
চিপ নির্দিষ্ট জিনিসগুলি উদাহরণস্বরূপ হতে পারে, মাইক্রোকন্ট্রোলারগুলি প্রায়শই ব্যাটারি ভিত্তিক সিস্টেমে ব্যবহৃত হয়, তাই খুব কম শক্তি তাই বেশিরভাগ পেরিফেরাল বন্ধ হয়ে রিসেট থেকে বেরিয়ে আসে এবং আপনাকে এই সাব সিস্টেমগুলির প্রতিটি চালু করতে হবে যাতে আপনি সেগুলি ব্যবহার করতে পারেন । Uarts, gpio, ইত্যাদি প্রায়শই একটি স্ফটিক বা অভ্যন্তরীণ দোলক থেকে সরাসরি স্বল্প-ইশ ঘড়ির গতি ব্যবহার করা হয়। এবং আপনার সিস্টেম ডিজাইনে দেখাতে পারে যে আপনার একটি দ্রুত ঘড়ি দরকার, তাই আপনি এটি আরম্ভ করুন। আপনার ঘড়িটি ফ্ল্যাশ বা র্যামের জন্য খুব দ্রুত হতে পারে তাই আপনাকে ঘড়ির উপরের চাপ দেওয়ার আগে ওয়েট স্টেটগুলি পরিবর্তন করতে হতে পারে। ইউআর্ট, অথবা ইউএসবি বা অন্যান্য ইন্টারফেস সেটআপ করা দরকার। তাহলে আপনার অ্যাপ্লিকেশনটি এটি করতে পারে।
একটি কম্পিউটার ডেস্কটপ, ল্যাপটপ, সার্ভার এবং একটি মাইক্রোকন্ট্রোলার তারা কীভাবে বুট / কাজ করে তা আলাদা নয়। এগুলি বাদ দিয়ে তারা বেশিরভাগই একটি চিপে থাকে না। বায়োস প্রোগ্রামটি প্রায়শই সিপিইউ থেকে আলাদা চিপ ফ্ল্যাশ / রোমে থাকে। যদিও সম্প্রতি x86 সিপাস একই প্যাকেজে সাপোর্ট চিপস ব্যবহার করত তার আরও বেশি বেশি টানছে (পিসিআই কন্ট্রোলার ইত্যাদি) তবে আপনার এখনও আপনার বেশিরভাগ র্যাম এবং রোম অফ চিপ বন্ধ রয়েছে তবে এটি এখনও একটি সিস্টেম এবং এটি এখনও ঠিক কাজ করে একটি উচ্চ স্তরে একই। সিপিইউ বুট প্রক্রিয়াটি সুপরিচিত, বোর্ড ডিজাইনাররা ফ্ল্যাশ / রোমটিকে ঠিকানার জায়গাতে রেখে দেয় যেখানে সিপিইউ বুট হয়। এই প্রোগ্রামটি (একটি x86 পিসিতে বিআইওএসের অংশ) উপরে বর্ণিত সমস্ত জিনিস করে, এটি বিভিন্ন পেরিফেরিয়ালগুলি শুরু করে, এটি ড্রামকে আরম্ভ করে, পিসি বাসগুলি গণনা করে, ইত্যাদি। বায়োস সেটিংসের উপর ভিত্তি করে ব্যবহারকারী বা প্রায়শই আমরা সেমিওস সেটিংস কল করে যা ব্যবহারকারীর দ্বারা প্রায়শই বেশ কনফিগার করা যায়, কারণ সেই সময়ে প্রযুক্তিটি কী ব্যবহৃত হত what কিছু যায় আসে না, এমন কিছু ব্যবহারকারীর সেটিংস রয়েছে যা আপনি যেতে পারেন এবং বায়োস বুট কোডটি কীভাবে পরিবর্তিত হয় তা কীভাবে তা জানাতে পরিবর্তন করতে পারেন।
বিভিন্ন লোকেরা বিভিন্ন পরিভাষা ব্যবহার করবে। একটি চিপ বুট, এটি প্রথম কোড চালিত হয়। কখনও কখনও বুটস্ট্র্যাপ বলা হয়। লোডার শব্দের সাহায্যে বুটলোডারটির অর্থ হ'ল আপনি যদি হস্তক্ষেপ করতে কিছু না করেন তবে এটি একটি বুটস্ট্র্যাপ যা আপনাকে জেনেরিক বুটিং থেকে আরও বড় কিছুতে নিয়ে যায়, আপনার অ্যাপ্লিকেশন বা অপারেটিং সিস্টেম। তবে লোডার অংশটি বোঝায় যে আপনি বুট প্রক্রিয়াটি বাধাগ্রস্থ করতে পারেন এবং তারপরে সম্ভবত অন্যান্য পরীক্ষার প্রোগ্রামগুলি লোড করতে পারেন। যদি আপনি এমবেডেড লিনাক্স সিস্টেমে উদাহরণস্বরূপ কখনও ইউবুট ব্যবহার করেন, আপনি একটি কী চাপতে পারেন এবং সাধারণ বুটটি থামাতে পারেন তবে আপনি একটি পরীক্ষার কার্নেলটিকে রামে ডাউনলোড করতে পারেন এবং ফ্ল্যাশটিতে থাকা একের পরিবর্তে এটি বুট করতে পারেন, বা আপনি আপনার ডাউনলোড করতে পারেন নিজস্ব প্রোগ্রাম, বা আপনি নতুন কার্নেলটি ডাউনলোড করতে পারেন তারপরে বুটলোডার এটি ফ্ল্যাশ করতে লিখতে পারে যাতে পরের বার আপনি এটি বুট করে নতুন স্টাফটি চালায়।
যতক্ষণ না সিপিইউ নিজেই, মূল প্রসেসর, যা পেরিফেরিয়াল থেকে ফ্ল্যাশ থেকে রাম জানে না। বুটলোডার, অপারেটিং সিস্টেম, অ্যাপ্লিকেশন সম্পর্কে কোনও ধারণা নেই। এটি সিপিইউতে কার্যকর করার জন্য নির্দেশাবলীর একটি ক্রম মাত্র। এগুলি একে অপরের থেকে বিভিন্ন প্রোগ্রামিং কার্যকে পৃথক করার সফ্টওয়্যার শর্তাদি। একে অপরের থেকে সফ্টওয়্যার ধারণা।
কিছু মাইক্রোকন্ট্রোলারগুলির একটি পৃথক ফ্ল্যাশ বা ফ্ল্যাশের পৃথক স্থানে চিপ বিক্রেতার দ্বারা সরবরাহিত একটি পৃথক বুটলোডার রয়েছে যা আপনি সংশোধন করতে পারবেন না। এক্ষেত্রে প্রায়শই একটি পিন বা পিনের সেট থাকে (আমি তাদের স্ট্র্যাপ বলি) যে রিসেট প্রকাশের আগে আপনি এগুলিকে উচ্চ বা নীচে বেঁধে রাখলে আপনি যুক্তি এবং / অথবা সেই বুটলোডারকে কী করতে হবে তা বলছেন, উদাহরণস্বরূপ একটি স্ট্র্যাপ সমন্বয় হতে পারে চিপটিকে সেই বুটলোডারটি চালানোর জন্য বলুন এবং ফ্ল্যাশটিতে ডেটা প্রোগ্রাম করার জন্য ইউআর্টে অপেক্ষা করুন। স্ট্রিপগুলি অন্য উপায়ে সেট করুন এবং চিপ বিক্রেতাদের বুটলোডার নয়, আপনার প্রোগ্রাম বুট করে চিপের ফিল্ড প্রোগ্রামিংয়ের জন্য অনুমতি দেয় বা আপনার প্রোগ্রাম ক্র্যাশ হয়ে পুনরুদ্ধার করে। কখনও কখনও এটি খাঁটি যুক্তি যা আপনাকে ফ্ল্যাশ প্রোগ্রাম করার অনুমতি দেয়। আজকাল এটি বেশ সাধারণ,
বেশিরভাগ মাইক্রোকন্ট্রোলারদের রামের চেয়ে অনেক বেশি ফ্ল্যাশ হওয়ার কারণটি হ'ল প্রাথমিক ব্যবহারের ক্ষেত্রে প্রোগ্রামটি সরাসরি ফ্ল্যাশ থেকে চালানো হয় এবং কেবল স্ট্যাক এবং ভেরিয়েবলগুলি coverাকতে পর্যাপ্ত মেষ থাকে। যদিও কিছু ক্ষেত্রে আপনি রাম থেকে প্রোগ্রামগুলি চালনা করতে পারেন যা আপনাকে ডান সংকলন করতে হবে এবং ফ্ল্যাশ সংরক্ষণ করতে হবে তারপরে কল করার আগে অনুলিপি করুন।
সম্পাদনা
flash.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
notmain.c
int notmain ( void )
{
unsigned int x=1;
unsigned int y;
y = x + 1;
return(0);
}
flash.ld
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
.bss : { *(.bss*) } > ted
.data : { *(.bss*) } > ted AT > bob
}
সুতরাং এটি কর্টেক্স-এম 0 এর জন্য একটি উদাহরণ, কর্টেক্স-এমএস সমস্ত এই উদাহরণ হিসাবে যতটা কাজ করে। নির্দিষ্ট চিপ, উদাহরণস্বরূপ, আর্ম অ্যাড্রেস স্পেসে 0x00000000 ঠিকানায় অ্যাপ্লিকেশন ফ্ল্যাশ এবং 0x20000000 এ র্যাম রয়েছে।
কর্টেক্স-এম বুটগুলি যেভাবে ঠিকানাতে 0x0000 এ 32 বিট শব্দ হয় তা স্ট্যাক পয়েন্টার সূচনা করার ঠিকানা। আমার এই উদাহরণের জন্য খুব বেশি স্ট্যাকের দরকার নেই তাই 0x20001000 যথেষ্ট হবে, স্পষ্টতই সেই ঠিকানার নীচে ভেড়া থাকতে হবে (বাহুটি যেভাবে ধাক্কা দেয়) এটি কি প্রথমে সাবট্র্যাক্ট করে ধাক্কা দেয় তাই যদি আপনি 0x20001000 সেট করেন তবে স্ট্যাকের প্রথম আইটেমটি ঠিকানায় 0x2000FFFC এ রয়েছে আপনাকে 0x2000FFFC ব্যবহার করতে হবে না)। ঠিকানা 0x0004 এ 32 বিট শব্দটি হ'ল রিসেট হ্যান্ডলারের ঠিকানা, মূলত প্রথম কোড যা রিসেটের পরে চলে। তারপরে আরও বিঘ্নিত এবং ইভেন্ট হ্যান্ডলার রয়েছে যা সেই কর্টেক্স এম কোর এবং চিপের সাথে সুনির্দিষ্ট, সম্ভবত আপনি 128 বা 256 এর মতো ব্যবহার করেন, যদি আপনি তাদের ব্যবহার না করেন তবে আপনাকে তাদের জন্য টেবিল সেটআপ করতে হবে না, আমি কয়েকজনকে বিক্ষোভের জন্য ফেলেছি উদ্দেশ্য।
এই উদাহরণে আমাকে .ডাটা বা .bss নিয়ে কাজ করার দরকার নেই কারণ আমি ইতিমধ্যে জানি যে কোডগুলি দেখে এই বিভাগগুলিতে কিছুই নেই। যদি সেখানে থাকে তবে আমি এটি মোকাবেলা করব এবং এক সেকেন্ডের মধ্যেই যাব।
সুতরাং স্ট্যাকটি সেটআপ, চেক, ড্যাটা যত্ন নেওয়া, চেক, বিএসএস, চেক, যাতে সি বুটস্ট্র্যাপ স্টাফ সম্পন্ন হয়, সি এর জন্য প্রবেশ ফাংশনে শাখা করতে পারে কারণ কিছু সংকলক যদি ফাংশনটি দেখেন তবে অতিরিক্ত জাঙ্ক যোগ করবেন প্রধান () এবং প্রধান পথে, আমি সেই সঠিক নামটি ব্যবহার করি না, আমি এখানে আমার সি এন্ট্রি পয়েন্ট হিসাবে নোটমেন () ব্যবহার করেছি। সুতরাং রিসেট হ্যান্ডলার কল করুন notmain () তবে / যদি notmain () ফেরত দেয় তবে এটি ঝুলতে চলে যায় যা কেবল অসীম লুপ, সম্ভবত খারাপ নামকরণ।
আমি দৃ master়ভাবে এই সরঞ্জামগুলিতে দক্ষতা অর্জনে বিশ্বাস করি, অনেক লোকই তা করেন না তবে আপনি যেটি পাবেন তা হ'ল প্রতিটি খালি ধাতব বিকাশকারী তার নিজের কাজটি করে, প্রায় সম্পূর্ণ স্বাধীনতার কারণে, আপনি অ্যাপস বা ওয়েব পৃষ্ঠাগুলি তৈরির মতো দূরবর্তীভাবে সীমাবদ্ধ নন not । তারা আবার তাদের নিজস্ব কাজ করে। আমি নিজের বুটস্ট্র্যাপ কোড এবং লিঙ্কার স্ক্রিপ্টটি পছন্দ করি। অন্যরা সরঞ্জামচেনের উপর নির্ভর করে, বা বিক্রেতার স্যান্ডবক্সে খেলেন যেখানে বেশিরভাগ কাজ অন্য কারও দ্বারা করা হয় (এবং যদি কিছু কিছু ভেঙে যায় তবে আপনি আঘাতের জগতে রয়েছেন, এবং খালি ধাতব জিনিসগুলি প্রায়শই এবং নাটকীয় উপায়ে ভেঙে যায়)।
সুতরাং আমি প্রাপ্ত gnu সরঞ্জামগুলির সাথে একত্রিত, সংকলন এবং লিঙ্কিং:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, fp, lsl r0
c: 0000001b andeq r0, r0, fp, lsl r0
10: 0000001b andeq r0, r0, fp, lsl r0
00000014 <reset>:
14: f000 f802 bl 1c <notmain>
18: e7ff b.n 1a <hang>
0000001a <hang>:
1a: e7fe b.n 1a <hang>
0000001c <notmain>:
1c: 2000 movs r0, #0
1e: 4770 bx lr
সুতরাং বুটলোডার কীভাবে জানেন যে স্টাফ রয়েছে। কারণ সংকলকটি কাজটি করেছিল। প্রথম ক্ষেত্রে এসেম্ব্লার ফ্ল্যাশ.এস এর জন্য কোড তৈরি করে এবং এটি করে লেবেলগুলি কোথায় রয়েছে তা জানেন (লেবেলগুলি ঠিক ফাংশনের নাম বা ভেরিয়েবলের নাম ইত্যাদির মতো ঠিক ঠিকানা) তাই আমাকে বাইটগুলি গণনা করতে এবং ভেক্টরটি পূরণ করতে হয়নি টেবিলটি ম্যানুয়ালি, আমি একটি লেবেলের নাম ব্যবহার করেছি এবং সমাবেশটি আমার জন্য এটি করেছিল। এখন আপনি জিজ্ঞাসা করুন, যদি রিসেটটি 0x14 ঠিকানা হয় তবে এসেম্ব্লার কেন ভেক্টর টেবিলে 0x15 রাখে। ভাল এটি একটি কর্টেক্স-এম এবং এটি বুট হয় এবং কেবল থাম্ব মোডে চলে। আর্মের সাহায্যে আপনি যখন কোনও ঠিকানায় শাখা করেন যদি থাম্ব মোডে শাখা করা হয় lsbit সেট করা দরকার, যদি আর্ম মোডটি পুনরায় সেট করা হয়। সুতরাং আপনি সর্বদা যে বিট সেট প্রয়োজন। আমি সরঞ্জামগুলি এবং লেবেলের আগে .thumb_func লাগিয়ে জানি, যদি সেই লেবেলটি ভেক্টর টেবিলের মতো ব্যবহার করা হয় বা ব্রাঞ্চ করার জন্য বা যে কোনও ক্ষেত্রে। টুলচেইন lsbit সেট করতে জানে। সুতরাং এটি 0x14 | 1 = 0x15 এখানে আছে। একইভাবে ফাঁসি জন্য। এখন বিচ্ছিন্নকরণকারী কল করতে notx () কল করার জন্য 0x1D দেখায় না তবে যন্ত্রগুলি সঠিকভাবে নির্দেশিকাটি তৈরি করেছে তা নিয়ে চিন্তা করবেন না।
এখন সেই কোডটি নোমেনে, সেই স্থানীয় ভেরিয়েবলগুলি ব্যবহৃত হয় না, তারা ডেড কোড। সংকলক এমনকি y সেট করে ব্যবহার করে তা বলে মন্তব্য করে।
ঠিকানার জায়গাগুলি নোট করুন, এই জিনিসগুলি সমস্ত 0x0000 ঠিকানায় শুরু হয় এবং সেখান থেকে যান যাতে ভেক্টর টেবিলটি সঠিকভাবে স্থাপন করা হয়, টেক্সট বা প্রোগ্রাম স্পেসটিও সঠিকভাবে স্থাপন করা হয়, কীভাবে আমি notmain.c এর কোডের সামনে ফ্ল্যাশ পেয়েছি by সরঞ্জামগুলি জানা, একটি সাধারণ ভুল হ'ল সঠিক না হওয়া এবং ক্রাশ হওয়া এবং শক্ত পোড়া না করা। আইএমও আপনাকে প্রথম বার বুট করার আগে জিনিসগুলি ঠিকঠাক স্থাপন করা হয়েছে তা নিশ্চিত করতে আলাদা করতে হবে, একবার আপনার যদি সঠিক জায়গায় জিনিস থাকে তবে আপনাকে অবশ্যই প্রতিবার পরীক্ষা করতে হবে না। কেবল নতুন প্রকল্পগুলির জন্য বা তারা স্তব্ধ হয়ে থাকে।
এখন এমন কিছু যা কিছু লোককে অবাক করে তোলে তা হল যে কোনও দুটি কম্পাইলার একই ইনপুট থেকে একই আউটপুট উত্পাদন করবে বলে আশা করার কোনও কারণ নেই। এমনকি বিভিন্ন সেটিংস সহ একই সংকলক। ঝাঁকুনি ব্যবহার করে, llvm সংকলকটি অপটিমাইজেশন সহ এবং ছাড়াই এই দুটি আউটপুট পাই
llvm / ঝনঝন অপ্টিমাইজড
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, fp, lsl r0
c: 0000001b andeq r0, r0, fp, lsl r0
10: 0000001b andeq r0, r0, fp, lsl r0
00000014 <reset>:
14: f000 f802 bl 1c <notmain>
18: e7ff b.n 1a <hang>
0000001a <hang>:
1a: e7fe b.n 1a <hang>
0000001c <notmain>:
1c: 2000 movs r0, #0
1e: 4770 bx lr
অপ্টিমাইজড না
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, fp, lsl r0
c: 0000001b andeq r0, r0, fp, lsl r0
10: 0000001b andeq r0, r0, fp, lsl r0
00000014 <reset>:
14: f000 f802 bl 1c <notmain>
18: e7ff b.n 1a <hang>
0000001a <hang>:
1a: e7fe b.n 1a <hang>
0000001c <notmain>:
1c: b082 sub sp, #8
1e: 2001 movs r0, #1
20: 9001 str r0, [sp, #4]
22: 2002 movs r0, #2
24: 9000 str r0, [sp, #0]
26: 2000 movs r0, #0
28: b002 add sp, #8
2a: 4770 bx lr
সুতরাং এটি একটি মিথ্যা যা সংকলকটি সংযোজনটিকে অপ্টিমাইজ করেছিল, তবে এটি ভেরিয়েবলগুলির জন্য স্ট্যাকের উপর দুটি আইটেম বরাদ্দ করেছিল, যেহেতু এগুলি স্থানীয় ভেরিয়েবলগুলি তারা মেষের মধ্যে থাকে তবে স্ট্যাকের উপর স্থির ঠিকানাগুলিতে নয়, গ্লোবালগুলির সাথে দেখবে যে পরিবর্তন। তবে সংকলকটি বুঝতে পেরেছিল যে এটি সংকলনের সময় y নির্ণয় করতে পারে এবং রান সময় এটি গণনা করার কোনও কারণ নেই তাই এটি কেবল এক্স এর জন্য বরাদ্দ হওয়া স্ট্যাক স্পেসে 1 এবং y এর জন্য বরাদ্দকৃত স্ট্যাক স্পেসের জন্য 2 রাখে। সংকলক অভ্যন্তরীণ সারণীর সাহায্যে এই স্থানটিকে "বরাদ্দ" দেয় আমি ভেরিয়েবল ওয়য়ের জন্য স্ট্যাক প্লাস 0 এবং ভেরিয়েবল এক্সের জন্য স্ট্যাক প্লাস 4 ঘোষণা করি। সংস্থাপকটি কোডটি সি স্ট্যান্ডার্ড বা সি প্রোগ্রামারের এক্সপেটেশন অনুসারে যতক্ষণ তা প্রয়োগ করতে পারে তাই এটি করতে পারে। কম্পাইলারটি ফাংশনটির সময়কালের জন্য স্ট্যাক + 4 এ x রেখে যাওয়ার কোনও কারণ নেই,
যদি আমি এসেম্বেলারে একটি ফাংশন ডামি যুক্ত করি
.thumb_func
.globl dummy
dummy:
bx lr
এবং তারপর এটি কল
void dummy ( unsigned int );
int notmain ( void )
{
unsigned int x=1;
unsigned int y;
y = x + 1;
dummy(y);
return(0);
}
আউটপুট পরিবর্তন
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, fp, lsl r0
c: 0000001b andeq r0, r0, fp, lsl r0
10: 0000001b andeq r0, r0, fp, lsl r0
00000014 <reset>:
14: f000 f804 bl 20 <notmain>
18: e7ff b.n 1a <hang>
0000001a <hang>:
1a: e7fe b.n 1a <hang>
0000001c <dummy>:
1c: 4770 bx lr
...
00000020 <notmain>:
20: b510 push {r4, lr}
22: 2002 movs r0, #2
24: f7ff fffa bl 1c <dummy>
28: 2000 movs r0, #0
2a: bc10 pop {r4}
2c: bc02 pop {r1}
2e: 4708 bx r1
এখন যেহেতু আমাদের নেস্ট করা ফাংশন রয়েছে, নোটমাইন ফাংশনটির তার রিটার্ন ঠিকানাটি সংরক্ষণ করা দরকার, যাতে এটি নেস্টেড কলের জন্য রিটার্ন ঠিকানাটি ক্লোবার করতে পারে। এটি কারণ বাহুটি রিটার্নের জন্য একটি রেজিস্টার ব্যবহার করে, যদি এটি স্ট্যাকটি ব্যবহার করে যেমন একটি x86 বা অন্য কিছু ভালভাবে বলে ... এটি এখনও স্ট্যাকটি ভিন্নভাবে ব্যবহার করবে। এখন আপনি জিজ্ঞাসা করলেন কেন এটি r4 চাপল? ঠিক আছে, কলিং কনভেনশনটি খুব বেশি কাল আগে স্ট্যাকটি 32 বিটের পরিবর্তে একটি শব্দের বাউন্ডারের পরিবর্তে 64 বিট (দুই শব্দ) বাউন্ডারি ধরে রাখার জন্য পরিবর্তিত হয়েছিল। সুতরাং তাদের স্ট্যাকটি সারিবদ্ধ রাখতে কিছুটা চাপ দেওয়া দরকার, তাই সংকলক নির্বিচারে কোনও কারণে r4 বেছে নিয়েছিল, কেন তা বিবেচ্য নয়। আর 4-এ পপিং একটি বাগ হবে যদিও এই টার্গেটের কলিং কনভেনশন অনুসারে আমরা একটি ফাংশন কলের ক্লোবার আর 4 না, আমরা r3 এর মাধ্যমে আর0 ক্লোবার করতে পারি। r0 হল রিটার্ন মান value দেখে মনে হচ্ছে এটি লেজ অপটিমাইজেশন করছে doing
তবে আমরা দেখতে পাই যে এক্স এবং ওয়াই ম্যাথটি 2 এর একটি হার্ডকোডযুক্ত মানটিকে ডামি ফাংশনে পাস করার জন্য অনুকূলিত করা হয়েছে (ডামি একটি পৃথক ফাইলে বিশেষভাবে কোড করা হয়েছিল, এই ক্ষেত্রে asm তে, যাতে সংকলকটি সম্পূর্ণরূপে ফাংশন কলটিকে অনুকূল করতে পারে না, যদি আমার একটি ডামি ফাংশন থাকে যা কেবলমাত্র সিটিতে notmain.c এ ফিরে আসে optim অপটিমাইজারটি এক্স, ওয়াই এবং ডামি ফাংশন কলটি সরিয়ে ফেলত কারণ তারা সমস্ত মৃত / অব্যর্থ কোড)।
এছাড়াও নোট করুন যেহেতু ফ্ল্যাশ.এস কোডটি বৃহত্তর নোটমেন পেয়ে গেছে অন্যথায় এবং টুলচেইন আমাদের জন্য সমস্ত ঠিকানা প্যাচিংয়ের যত্ন নিয়েছে যাতে আমাদের ম্যানুয়ালি এটি করতে হবে না।
রেফারেন্সের জন্য অপ্রচলিত ঝনঝন
00000020 <notmain>:
20: b580 push {r7, lr}
22: af00 add r7, sp, #0
24: b082 sub sp, #8
26: 2001 movs r0, #1
28: 9001 str r0, [sp, #4]
2a: 2002 movs r0, #2
2c: 9000 str r0, [sp, #0]
2e: f7ff fff5 bl 1c <dummy>
32: 2000 movs r0, #0
34: b002 add sp, #8
36: bd80 pop {r7, pc}
অপ্টিমাইজড ঝনঝন
00000020 <notmain>:
20: b580 push {r7, lr}
22: af00 add r7, sp, #0
24: 2002 movs r0, #2
26: f7ff fff9 bl 1c <dummy>
2a: 2000 movs r0, #0
2c: bd80 pop {r7, pc}
এই সংকলক লেখক স্ট্যাকটি সারিবদ্ধ করার জন্য ডামি ভেরিয়েবল হিসাবে r7 ব্যবহার করতে পছন্দ করেছেন, এটি স্ট্যাক ফ্রেমে কিছু না থাকলেও এটি r7 ব্যবহার করে একটি ফ্রেম পয়েন্টার তৈরি করছে। মূলত নির্দেশটি অপ্টিমাইজ করা যেতে পারে। তবে এটি পপটি তিনটি নির্দেশ না দিয়ে ফিরে ব্যবহার করেছিল, সম্ভবত আমার উপরই আমি বাজি ধরেছিলাম যে আমি ডান কমান্ড লাইন অপশন (প্রসেসরের নির্দিষ্ট করে) দিয়ে জিসিসি পেতে পারি।
এটি বেশিরভাগ আপনার বাকি প্রশ্নের উত্তর দেওয়া উচিত
void dummy ( unsigned int );
unsigned int x=1;
unsigned int y;
int notmain ( void )
{
y = x + 1;
dummy(y);
return(0);
}
আমার এখন গ্লোবাল আছে। সুতরাং তারা অপটিমাইজড না হয়ে থাকলে .Data বা .bss এ প্রবেশ করে।
আমরা চূড়ান্ত আউটপুট দেখার আগে এর মধ্যবর্তী বস্তু তাকান
00000000 <notmain>:
0: b510 push {r4, lr}
2: 4b05 ldr r3, [pc, #20] ; (18 <notmain+0x18>)
4: 6818 ldr r0, [r3, #0]
6: 4b05 ldr r3, [pc, #20] ; (1c <notmain+0x1c>)
8: 3001 adds r0, #1
a: 6018 str r0, [r3, #0]
c: f7ff fffe bl 0 <dummy>
10: 2000 movs r0, #0
12: bc10 pop {r4}
14: bc02 pop {r1}
16: 4708 bx r1
...
Disassembly of section .data:
00000000 <x>:
0: 00000001 andeq r0, r0, r1
এখন এটি থেকে কোনও তথ্য অনুপস্থিত তবে এটি কী চলছে তার একটি ধারণা দেয়, লিঙ্কারটি হ'ল বস্তু গ্রহণ করে এবং তাদের সাথে লিঙ্ক করা তথ্য সরবরাহ করে (এই ক্ষেত্রে ফ্ল্যাশ.ল্ড) যেখানে এটি বলে যে টেক্সট এবং কোথায়। তথ্য এবং যেমন যায়। সংকলক এই জাতীয় জিনিস জানে না, এটি কেবল এটি উপস্থাপিত কোডের উপর দৃষ্টি নিবদ্ধ করতে পারে, কোনও বাহ্যিক সংযোগ পূরণ করার জন্য এটি কোনও লিঙ্কারের জন্য একটি ছিদ্র ছেড়ে দিতে হয়। যে কোনও ডেটাতে things জিনিসগুলিকে একসাথে যুক্ত করার উপায় ছেড়ে যেতে হবে, তাই সমস্ত সংখ্যার ঠিকানা এখানে শূন্যের ভিত্তিতে কেবল কারণ সংকলক এবং এই বিচ্ছিন্নকরণকারী জানেন না। লিঙ্কার জিনিস রাখার জন্য এখানে ব্যবহার করে এমন অন্য তথ্য এখানে দেখানো হয়নি। এখানে কোডটি যথেষ্ট পর্যায়ে স্বাধীন তাই লিঙ্কার তার কাজটি করতে পারে।
এরপরে আমরা সংযুক্ত আউটপুটটির কমপক্ষে একটি বিচ্ছিন্নতা দেখতে পাই
00000020 <notmain>:
20: b510 push {r4, lr}
22: 4b05 ldr r3, [pc, #20] ; (38 <notmain+0x18>)
24: 6818 ldr r0, [r3, #0]
26: 4b05 ldr r3, [pc, #20] ; (3c <notmain+0x1c>)
28: 3001 adds r0, #1
2a: 6018 str r0, [r3, #0]
2c: f7ff fff6 bl 1c <dummy>
30: 2000 movs r0, #0
32: bc10 pop {r4}
34: bc02 pop {r1}
36: 4708 bx r1
38: 20000004 andcs r0, r0, r4
3c: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <y>:
20000000: 00000000 andeq r0, r0, r0
Disassembly of section .data:
20000004 <x>:
20000004: 00000001 andeq r0, r0, r1
সংকলকটি মূলত র্যামে দুটি 32 বিট ভেরিয়েবলের জন্য বলেছে। একটি .bss এ আছে কারণ আমি এটি আরম্ভ করি নি তাই এটি শূন্য হিসাবে অনুমান করা হয়। অন্যটি .ডাটা কারণ আমি এটি ঘোষণার ভিত্তিতে শুরু করেছি।
এখন এটি বিশ্বব্যাপী পরিবর্তনশীল বলে ধরে নেওয়া হচ্ছে যে অন্যান্য ফাংশনগুলি সেগুলি সংশোধন করতে পারে। সংকলক কখন নোমেন বলা যায় সে সম্পর্কে কোনও অনুমান করে না তাই এটি যেটি দেখতে পারে তার সাথে y = x + 1 গণিতটি অনুকূল করতে পারে না, সুতরাং এটি রানটাইম করতে হবে। এটি রাম থেকে পড়তে হবে দুটি ভেরিয়েবল এগুলি যুক্ত করে ফিরে সংরক্ষণ করতে হবে।
এখন পরিষ্কারভাবে এই কোড কাজ করবে না। কেন? কারণ এখানে যেমন দেখানো হয়েছে আমার বুটস্ট্র্যাপটি নোমেন কল করার আগে র্যাম প্রস্তুত করে না, তাই চিপ যখন জেগেছিল তখন 0x20000000 এবং 0x20000004 এ যা কিছু আবর্জনা ছিল তা হ'ল y এবং x এর জন্য ব্যবহৃত হবে।
এখানে যে প্রদর্শন করতে যাচ্ছি না। আপনি আমার আরও দীর্ঘায়িত ঝাঁকুনি পড়তে পারেন .ডাটা এবং .bss এবং কেন আমি কখনই আমার খালি ধাতব কোডে এগুলি প্রয়োজন হয় না, তবে আপনি যদি মনে করেন যে অন্য কারও কাছে এটি আশা করার চেয়ে আপনি সরঞ্জামগুলি অর্জন করতে এবং দক্ষতা অর্জন করতে চান তবে .. ।
https://github.com/dwelch67/raspberrypi/tree/master/bssdata
লিঙ্কার স্ক্রিপ্ট এবং বুটস্ট্র্যাপগুলি কিছুটা সংকলক নির্দিষ্ট করে তাই আপনি একটি সংকলকের এক সংস্করণ সম্পর্কে যা কিছু শিখেন তা পরবর্তী সংস্করণে বা অন্য কোনও সংকলক সহ টস করতে পারে, তারপরেও আমি .ডাটা এবং .bss প্রস্তুতিতে প্রচুর পরিশ্রম না লাগানোর আরেকটি কারণ reason শুধু এই অলস হতে:
unsigned int x=1;
আমি বরং এটি করতে চাই
unsigned int x;
...
x = 1;
এবং সংকলকটি এটি আমার জন্য পাঠ্য দিন। কখনও কখনও এটি ফ্ল্যাশ সেভ করে কখনও কখনও এটি বেশি জ্বলতে থাকে। টুলচেন সংস্করণ বা অন্য একটি সংকলক থেকে প্রোগ্রাম এবং পোর্ট করা সবচেয়ে স্পষ্টভাবে সহজ। অনেক বেশি নির্ভরযোগ্য, কম ত্রুটিযুক্ত প্রবণ। হ্যাঁ, সি স্ট্যান্ডার্ডের সাথে খাপ খায় না।
এখন যদি আমরা এই স্থির গ্লোবালগুলি তৈরি করি?
void dummy ( unsigned int );
static unsigned int x=1;
static unsigned int y;
int notmain ( void )
{
y = x + 1;
dummy(y);
return(0);
}
আমরা হব
00000020 <notmain>:
20: b510 push {r4, lr}
22: 2002 movs r0, #2
24: f7ff fffa bl 1c <dummy>
28: 2000 movs r0, #0
2a: bc10 pop {r4}
2c: bc02 pop {r1}
2e: 4708 bx r1
স্পষ্টত those ভেরিয়েবলগুলি অন্য কোড দ্বারা সংশোধন করা যায় না, তাই সংকলক এখন সংকলন সময়ে ডেড কোডটিকে অপ্টিমাইজ করতে পারে, যেমনটি এর আগে করেছিল।
unoptimized
00000020 <notmain>:
20: b580 push {r7, lr}
22: af00 add r7, sp, #0
24: 4804 ldr r0, [pc, #16] ; (38 <notmain+0x18>)
26: 6800 ldr r0, [r0, #0]
28: 1c40 adds r0, r0, #1
2a: 4904 ldr r1, [pc, #16] ; (3c <notmain+0x1c>)
2c: 6008 str r0, [r1, #0]
2e: f7ff fff5 bl 1c <dummy>
32: 2000 movs r0, #0
34: bd80 pop {r7, pc}
36: 46c0 nop ; (mov r8, r8)
38: 20000004 andcs r0, r0, r4
3c: 20000000 andcs r0, r0, r0
এই সংকলকটি যা স্থানীয়দের জন্য স্ট্যাক ব্যবহার করেছিল, এখন গ্লোবালগুলির জন্য র্যাম ব্যবহার করে এবং লিখিত হিসাবে এই কোডটি নষ্ট হয়ে গেছে কারণ আমি .Data বা .bss সঠিকভাবে পরিচালনা করি নি।
এবং একটি সর্বশেষ জিনিস যা আমরা বিচ্ছিন্নতার মধ্যে দেখতে পাচ্ছি না।
:1000000000100020150000001B0000001B00000075
:100010001B00000000F004F8FFE7FEE77047000057
:1000200080B500AF04480068401C04490860FFF731
:10003000F5FF002080BDC046040000200000002025
:08004000E0FFFF7F010000005A
:0400480078563412A0
:00000001FF
আমি 0x12345678 এর সাথে প্রি-ইন হয়ে এক্স পরিবর্তন করেছি। আমার লিঙ্কার স্ক্রিপ্ট (এটি gnu ld এর জন্য) বব জিনিসটিতে এই টেড রয়েছে। এটি লিঙ্কারে বলছে আমি চূড়ান্ত জায়গাটি টেড ঠিকানার জায়গায় থাকতে চাই, তবে এটি টেড ঠিকানার জায়গায় বাইনারি রেখে সঞ্চয় করব এবং কেউ আপনার জন্য এটি স্থানান্তরিত করবে। এবং আমরা দেখতে পেয়েছি যে ঘটেছে। এটি ইন্টেল হেক্স ফর্ম্যাট। এবং আমরা 0x12345678 দেখতে পাচ্ছি
:0400480078563412A0
বাইনারি ফ্ল্যাশ ঠিকানা স্পেসে হয়।
পাঠকরাও এটি দেখায়
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x010040 0x00000040 0x00000040 0x00008 0x00008 R 0x4
LOAD 0x010000 0x00000000 0x00000000 0x00048 0x00048 R E 0x10000
LOAD 0x020004 0x20000004 0x00000048 0x00004 0x00004 RW 0x10000
LOAD 0x030000 0x20000000 0x20000000 0x00000 0x00004 RW 0x10000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
LOAD লাইন যেখানে ভার্চুয়াল ঠিকানা 0x20000004 এবং দৈহিক 0x48