ساختار فایل اجرایی رو می توانید اینجا ببینید، مطلب خیلی مفصلی ئه :
PE Format
اگه با دقت بررسی اش کنید می بینید که ساختار ساده ای نداره و نوشتنش کار راحتی نیست.
بخش هایی مثل پشته موقع اجرا شدن برنامه در حافظه ایجاد می شه، اندازه اش در فایل اجرایی مشخص میشه ولی خودش در فایل اجرایی نیست.
سیستم عامل الزاما همه کد اجرایی رو در از ابتدا در حافظه قرار نمیده، یک بخش آغازین رو که حالا ممکنه چند page باشه فراخوانی می کنه و در ادامه اجرای برنامه بر اساس اینکه اجرا چطور باشه page های مورد نیاز فراخوانی می شوند. داده ها و حافظه مورد نیاز برنامه هم بر اساس درخواست خود کد به تدریج تخصیص پیدا می کنه.
از طرف دیگه کد ماشین داخل فایل اجرایی بر اساس آدرس های نسبی ذخیره شده، آدرس های مطلق نیستند، یعنی مثلا نمیگه داده رو از آدرس x از حافظه RAM بخون، میگه داده رو از x بایت جلوتر از آدرس شروع حافظه خود برنامه بخون. آدرس شروع برنامه کجا است؟ هنوز مشخص نیست، موقع اجرای برنامه مشخص میشه. دلیل این ذخیره شدن آدرس بصورت نسبی اینه که موقع ساختن فایل اجرایی نمیدونیم که موقع اجرا در کدوم آدرس از حافظه فراخوانی میشه. هر بار در یک جای متفاوتی میتونه فراخوانی بشه.
برای همین یک بخش مهم از فایل اجرایی جدول Relocation ئه که مشخص میکنه کجاهای کد آدرس نسبی ذخیره شده که باید موقع اجرای برنامه که کد در حافظه قرار می گیره، آدرس اش از نسبی به آدرس مطلق تبدیل بشه. از این جهت جدا کردن بخش اجرایی به تنهایی یک کد غیر قابل اجرا بهتون تحویل میده، برای اینکه پردازنده اون رو درک کنه باید اول جدول Relocation رو روی اون کد پردازش کنید. ساختار فایل اجرایی ساختار ساده ای نیست.
پیاده سازی همه چیزی که میخواهید کار خیلی سختی است، عملی است و ولی مدت خیلی طولانی باید وقت صرف مطالعه مستندات جور واجور کنید.
پیشنهاد می کنم که کامپایلر زبان دیگری رو واسطه کنید، مثلا هدف رو این قرار بدید که بجای ساختن فایل اجرایی، برنامه یا کامپایلر تون نهایتا یک فایل کد اسمبلی (فایل متنی ASM) بسازه تا بتوانید برای ایجاد فایل EXE نهایی از اسمبلر ها و لینکر موجود برای ویندوز کمک بگیرید، وگرنه رعایت اصول نوشتن کد ماشین و ساختار فایل EXE کار تون رو خیلی خیلی سخت می کنه.
برای درک فایل اجرایی ابزار هایی مثل PE Explorer و W32Dasm کمکتون می کنه.