بررسی قراردادهای فراخوانی (convention)
اضافه کردن یک ماژول اسمبلی به پروژه
- در بعضی پروژه ها ممکن است که نیاز به نوشتن تکه های خاصی از یک کد سورس در زبان اسمبلی باشد. این آموزش اول نشان می دهد که چگونه کامپایلر می تواند در بررسی فراخوانی قرارداد مفید باشد، که شما باید آشنا باشید و یا آشنا شوید وقتی که ماژول اسمبلی از ماژول ++C/C فراخوانی می شود و یا برعکس این حالت. علاوه بر این ، این آموزش نشان می دهد که چگونه شما می توانید به آسانی سورس ماژول نوشته شده با C را با ماژول اسمبلی ترکیب کنید، و همین طور این روش قابل اعمال به پروژه ای است که سورس ماژول آن در زبان ++C نوشته شده است.
- در این آموزش فرض بر این است که شما با اصول پایه نرم افزار که در آموزش های قبلی توصیف شده است آشنایی دارید.
بررسی قراردادهای فراخوانی (convention)
وقتی شما یک کد اسمبلی می نویسید که از یک کد C فراخوانی شده است ، شما باید نسبت به قرداد فراخوانی که کامپایلر از آن استفاده می کند آگاهی داشته باشید. اگر شما اسکلتی از کد C ایجاد کنید و به کامپایلر اجازه دهید که از روی آن فایل خروجی اسمبلی را تولید کند ، شما می توانید فایل خروجی اسمبلی تولید شده را مطالعه کنید و جزئیات بیشتری نسبت به قرارداد فرخوانی را پیدا کنید.
در این مثال شما یک فایل خروجی اسمبلی را از فایل Utilities.c کامپایل و ایجاد خواهید کرد.( در واقع آن را make خواهید کرد.)
- یک پروژه جدید (create a new project)در همان میزکاری(workspace) قبلی خود که در آموزش قبلی ایجاد کرده بودید بسازید و اسم پروژه را project2 قرار دهید.
- فایل های Tutor.c و Utilities.c را به پروژه خود اضافه کنید.
برای نمایش کلی میز کاری خود و یا همان workspace ، بر روی زبانه Overview کلیک کنید ، همانند تصویر زیر که در پایین تصویر قرار دارد. برای فقط دیدن پروژه جدید ایجاد شده ، بر روی زبانه project2 کلیک کنید . حالا شما همانند شکل زیر پروژه جدید خود را باید ببینید.
- برای تنظیم options ، با انتخاب Project>Options ، و انتخاب پوشه General Options و سرانجام بر روی Ok کلیک کنید.
- برای تنظیمات فایل Utilities.c در پنجره workspace بر روی فایل کلیک کنید .
با انتخاب Project>Options توجه داشته باشید که فقط پوشه های C/C++ Compiler و Custom Build قابل دسترس هستند.
- در پوشه C/C++ Compiler ، با انتخاب گزینه Override inherited settings و تنظیمات جدید را به صورت زیر اعمال کنید.
Option | Page |
(Level: None (Best debug support | Optimizations |
Output assembler file Include source (Include call frame information (must be deselected | List |
توجه: در این مثال برای نمایش متغیر های قابل دسترس محلی و سراسری ، شما باید در تنظیمات Optimizations سطح Low را انتخاب کنید وقتی که کد را کامپایل می کنید. اگر شما در تنظیمات Optimization سطح higher را استفاده کنید ، منابع مورد نیاز برای متغییر های محلی ممکن است حذف شود. اما ، دستورات توابع حقیقی با هر نوع تنظیم سطح Optimization تغییری نمی کند.
- بر روی Ok کلیک کنید تا به پنجره Workspace برگردید.
- فایل Utilities.c را کامپایل کنید. شما می توانید فایل تولید شده خروجی Utilities.s را در پوشه پروژه خود در debug\list پیدا کنید.
توجه: اگر شما در هنگام نصب نرم افزار محدودیت در نصب داشته باشید و به درستی کرک نکرده باشید ، فایل اسمبلی ممکن است که تولید نشود . در این مورد شما می توانید فایل از قبل تولید شده را مطالعه کنید ، در پوشه tutor که در محل نصب نرم افزار قرار دارد.
- برای بررسی قرداد فراخوانی و دیدن چگونگی نمایش کد C و یا ++C به زبان اسمبلی ، فایل Utilities.s را باز کنید.
شما می توانید حالا مطالعه کنید که کجا و چگونه پارامتر ها قرار می گیرد، چگونه برنامه بر میگردد از جایی که فراخوانی شده بود ، و چگونه نتیجه مقادیر برمیگردد. شما همچنین می توانید ببینید که ریجستر ها در سطح روال اسمبلی حفظ می شوند.
توجه: فایل سورس اسمبلی تولید شده ممکن است شامل اطلاعات داخلی کامپایلر باشد ، برای مثال راهنمای های CFI. این رهنمودها برای اهداف اشکال زدایی در دسترس بوده و شما باید از این جزئیات صرف نظر کنید.
برای بدست آوردن رابط درستی برای توابع برنامه تان ، شما باید برای هر تابع که شما نیاز دارید یک اسکلت کد ایجاد کنید.
برای اطلاعات بیشتر درباره ی فراخوانی قرارداد که در کامپایلر استفاده می شود ، راهنمایی IAR C/C++ Development Guide for ARM را ببینید.
اضافه کردن یک ماژول اسمبلی به پروژه
این آموزش نشان می دهد که چگونه شما می توانید به آسانی یک پروژه که شامل هر دو ماژول اسمبلی و ماژول C است را ایجاد کنید. شما همچنین پروژه خود را کامپایل خواهید کرد و فایل لیست خروجی اسمبلی آن را هم خواهید دید.
شما یک ماژول اسمبلی که شامل یک تابع write__ است را اضافه خواهید کرد. این تابع یک تابع اولیه خروجی است ، که به وسیله putchar استفاده می شود و به تمام کاراکترهای خروجی رسیدگی می کند. اجرا استاندارد write__ کاراکترهای خروجی را تغییر مسیر می دهد به سمت پنجره ترمینال I/O در قسمت اشکال زدایی C-SPY . همچنین برای نسخه یا ورژن خودتان write__ را بسازید ، با ویژگی های اضافی است که خروجی آن با علامت * قبل از هر کاراکتر نوشته شده است.
در این قسمت از برنامه شما کافی است که تابع write.s را به پروژه خود اضافه کنید در پوشه ای که نرم افزار خود را نصب کرده اید از پوشه tutor.
- با اضافه کردن فایل write.s پروژه project2 تغییر می کند.
توجه: برای دیدن فایل اسمبلی در قسمت پنجره دیالوگ Add files که با انتخاب Project>Add Files پنجره دیالوگ باز می شود . در حالت پیش فرض هم می توانید فایل های اسمبلی را ببینید ولی در قسمت منوی کشویی هم می توانید با انتخاب Assembler Files تنها فایل اسمبلی را نگاه کنید.
- با انتخاب پروژه جدید خود و انتخاب project2 در پنجره workspace ، و انتخاب Project>Options . از تنظیمات پیش فرض در پوشه General Options , C/C++ Compiler و Linker استفاده کنید . حال پوشه Assembler را انتخاب کنید ، بر روی زبانه List کلیک کنید و گزینه Output list file را انتخاب کنید تا فعال شود . حال بر روی OK کلیک کنید.
- حال فایل write.s را در پنجره workspace انتخاب کنید و بعد با انتخاب project>Compile فایل اسمبلی آن تولید خواهد شد.
در اینجا فرض بر آن است که فایل اسمبلی Write.o با موفقیت ایجاد شده است ، که شامل کد Linkable object است.
دیدن فایل لیست اسمبلر
- بر روی فایل Write.lst دابل کلیک کنید تا فایل باز شود. مکان فایل در پوشه output در پنجره Workspace قرار دارد که زیر مجموعه فایل Write.s است.
در انتهای فایل یک خلاصه ای از error ها و warning های تولید شده وجود دارد.
برای جزئیات بیشتر فرمت فایل لیست ، the ARM IAR Assembler Reference Guide را ببینید.
- با انتخاب Project>Make فایل خروجی project2.out تولید می شود.
- حال پروژه را با C-SPY اجرا کنید و رفتارها را که در آموزش برنامه قبلی بوده است مقایسه کنید و شباهت آن را ببینید. اما با یک تفاوت که قبل هر کاراکتر * نوشته شده است.
دیباگر را ببندید وقتی که کارتان را انجام دادید.