إخراج جمعية دول مجلس التعاون الخليجي لبرنامج فارغ على X86، Win32

StackOverflow https://stackoverflow.com/questions/1317081

  •  19-09-2019
  •  | 
  •  

سؤال

أكتب برامج فارغة لإزعاج الجحيم من المبرمجين Stackoverflow، وليس. أنا فقط استكشاف Toolchain جنو.

الآن قد يكون ما يلي عميقا جدا بالنسبة لي، ولكنه في الاستمرار في البرنامج الفارغ الذي بدأته في فحص إخراج مترجم C، والأشياء جنو تستهلك.

gcc version 4.4.0 (TDM-1 mingw32)

test.c:

int main()
{
    return 0;
}

GCC -S Test.C.

    .file   "test.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    call    ___main
    movl    $0, %eax
    leave
    ret 

هل يمكنك شرح ما يحدث هنا؟ هنا جهدي لفهمها. لقد استخدمت as دليل ودليل X86 ASM المعرفة:

  • .file "test.c" هو التوجيه للحصول على اسم الملف المنطقي.
  • .def: وفقا للمستندات "البدء في تحديد معلومات تصحيح الأخطاء للحصول على اسم رمز". وبعد ما هو الرمز (اسم وظيفة / متغير؟) وأي نوع من معلومات التصحيح؟
  • .scl: مستندات يقول "قد علم فئة التخزين ما إذا كان رمز ثابت أو خارجي". وبعد هل هذا هو نفسه ثابتة و خارجي أنا أعرف من ج؟ وماذا هو "2"؟
  • .type: يخزن المعلمة "كعمل نوع من إدخال جدول الرمز", ، ليس لدي أي فكرة.
  • .endef: لا مشكلة.
  • .text: الآن هذا هو مشكلة، يبدو أنه شيء يسمى القسم وأنا قرأت أن مكانه للحصول على التعليمات البرمجية، لكن المستندات لم تخبرني كثيرا.
  • .globl "يجعل الرمز مرئيا إلى LD.", ، الدليل واضح تماما على هذا.
  • _main: قد يكون هذا هو عنوان التشغيل (؟) لوظيفتي الرئيسية
  • pushl_: دفع طويل (32 بت)، الذي الأماكن EBP على المكدس
  • movl: خطوة 32 بت. Pseudo-C: EBP = ESP;
  • andl: منطقي و. Pseudo-C: ESP = -16 & ESP, أنا لا أرى حقا ما هي نقطة هذا.
  • call: يدفع IP إلى المكدس (لذلك يمكن للإجراء المسمى العثور على طريقه مرة أخرى) ويستمر فيها __main يكون. (ما هو __main؟)
  • movl: يجب أن يكون هذا الصفر هو ثابت أعود في نهاية التعليمات البرمجية. تضع MOV هذا الصفر في EAX.
  • leave: يستعيد كومة بعد تعليمات الدخول (؟). لماذا ا؟
  • ret: يعود إلى عنوان التعليمات الذي يتم حفظه على المكدس

شكرا لك على مساعدتك!

هل كانت مفيدة؟

المحلول

.file "test.c"

أوامر تبدأ مع. هي توجيهات للمجمع. هذا يقول فقط هذا هو "ملف file.c"، يمكن تصدير هذه المعلومات إلى معلومات تصحيح الأخطاء من EXE.

.def ___main؛ .scl 2؛ . Type 32؛ .endef.

تعرف توجيهات .DEF رمز تصحيح الأخطاء. SCL 2 يعني تخزين فئة 2 (فئة التخزين الخارجية). يقول Type 32 إن هذه Sumbol هي وظيفة. سيتم تعريف هذه الأرقام بواسطة تنسيق PE-COFT EXE

___Main هي وظيفة تسمى التي تعتني بإعصار الأحذية التي يحتاجها دول مجلس التعاون الخليجي (سوف تفعل أشياء مثل Run C ++ Inticizers ثابتة وغيرها من التدبير المنزلي اللازم).

.text

يبدأ قسم النص - رمز حياة هنا.

.globll _main.

يحدد رمز _main باسم Global، والذي سيجعله مرئيا إلى الرابط والوحدات الأخرى المرتبطة بها.

.def        _main;  .scl    2;      .type   32;     .endef

نفس الشيء مثل _main، يخلق رموز تصحيح الأخطاء تفيد بأن _main وظيفة. هذا يمكن استخدامه من قبل الهياجين.

_رئيسي:

يبدأ ملصق جديد (سوف ينتهي عنوان). إن التوجيه .globlbl أعلاه يجعل هذا العنوان مرئيا للكيانات الأخرى.

pushl       %ebp

يحفظ مؤشر الإطار القديم (سجل EBP) على المكدس (حتى يمكن وضعه في مكانه عند انتهاء هذه الوظيفة)

movl        %esp, %ebp

ينقل مؤشر المكدس إلى سجل EBP. غالبا ما يسمى EBP مؤشر الإطار، حيث يشير إلى أعلى قيم المكدس داخل "الإطار" الحالي (وظيفة "عادة)، (بالإشارة إلى المتغيرات الموجودة على المكدس عبر EBP يمكن أن تساعد المصاجرين)

أندل $ -16،٪ esp

و ands المكدس مع FFFFFFFF0 الذي يحاذيه بشكل فعال على حدود 16 بايت. الوصول إلى القيم المحاذاة على المكدس أسرع بكثير مما لو كانوا غير إجماليين. كل هذه التعليمات السابقة هي prologue وظيفة قياسية.

call        ___main

يستدعي وظيفة ___main التي ستقوم بتهيئة الأشياء التي يحتاجها دول مجلس التعاون الخليجي. سيؤدي المكالمة إلى دفع مؤشر التعليمات الحالية على المكدس والقفز إلى عنوان ___main

movl        $0, %eax

نقل 0 إلى سجل EAX، (0 في المقابل 0؛) يتم استخدام سجل EAX لعقد قيم إرجاع وظيفة لاتفاقية الاتصال STDCALL.

غادر

تعليمات الإجازة اختصار إلى حد كبير

movl     ebp,esp
popl     ebp

أي أنها "التراجع" التي تم القيام بها بالأشياء في بداية الوظيفة - استعادة مؤشر الإطار والمكدس إلى حالتها السابقة.

ريد

يعود إلى من يسمى هذه الوظيفة. سوف ينبثق مؤشر التعليمات من المكدس (التي ستوضع فيها إرشادات المكالمات المقابلة هناك) والقفز هناك.

نصائح أخرى

هناك تمرين مشابه للغاية محدد هنا: http://en.wikibooks.org/wiki/x86_assembly/gas_syntax.

لقد اكتشفت معظمها - سأحدث ملاحظات إضافية للتأكيد والإضافات.

__main هو روتين فرعي في مكتبة جنو القياسية التي تعتني بمختلف تهيئة بدء التشغيل. ليس من الضروري بدقة لبرامج ج ولكن مطلوب فقط في حالة ربط رمز C مع C ++.

_main هو الروتين الفرعي الرئيسي الخاص بك. كما كلاهما _main و __main هي مواقع التعليمات البرمجية لديهم نفس فئة التخزين والنوع. لم أفعل بعد التعاريف .scl و .type بعد. قد تحصل على بعض الإضاءة من خلال تحديد عدد قليل من المتغيرات العالمية.

تقوم التعليمات الثلاثة الأولى بإعداد إطار مكدس وهو مصطلح تقني لتخزين العمل من المتغيرات المحلية والمؤقتة بالنسبة للجزء الأكبر. دفع ebp يحفظ قاعدة إطار مكدس المتصل. وضع esp إلى ebp يضبط قاعدة إطار المكدس لدينا. ال andl قم بمحاذاة إطار المكدس إلى حدود 16 بايت فقط في حالة حدوث أي متغيرات محلية على المكدس تتطلب محاذاة 16 بايت (ل X86 لتعليمات SIMD تتطلب المحاذاة، ولكن محاذاة تسرع أنواع عادية مثل intرمل floatس.

في هذه المرحلة كنت تتوقع عادة esp للحصول على نقل في الذاكرة لتخصيص مساحة مكدس للمتغيرات المحلية. لك main ليس لديه أي دول مجلس التعاون الخليجي لا تهتم.

دعوة إلى __main هو خاص إلى نقطة الدخول الرئيسية ولن يظهر عادة في الروتين الفرعي.

الباقي يذهب كما remmised. يسجل eax هو المكان المناسب لوضع رموز الإرجاع الصحيحة في المواصفات الثنائية. leave يطل على إطار المكدس و ret يعود إلى المتصل. في هذه الحالة، المتصل هو وقت تشغيل C منخفض المستوى الذي سيفعل سحر إضافي (مثل الاتصال atexit() وظائف، اضبط رمز الخروج لهذه العملية واسأل نظام التشغيل إنهاء العملية.

حول ذاك أندل $ -16،٪ esp

  • 32 بت: -16 في العشرية يساوي 0xFFFFFF0 في التمثيل السداسي عشري
  • 64 بت: -16 في العشرية يساوي 0xFFFFFFFFFFF0 في التمثيل السداسي عشري

لذلك ستخفي الجزء الأخير من 4 بت من ESP (BTW: 2 ** 4 يساوي 16) وسوف يحتفظ بجميع البتات الأخرى (بغض النظر عما إذا كان النظام المستهدف هو 32 أو 64 بت).

كذلك إلى andl $-16,%esp, ، هذا يعمل لأن تحديد البتات المنخفضة إلى الصفر سوف تضبط دائما %esp أسفل في القيمة، وينتف على المكدس على x86.

ليس لدي كل إجابات ولكن يمكنني شرح ما أعرفه.

ebp يتم استخدامها من قبل الوظيفة لتخزين الحالة الأولية esp أثناء تدفقها، إشارة إلى أين تنتقل الحجج إلى الوظيفة وأين هي المتغيرات المحلية الخاصة بها. أول شيء يفعله الوظيفة هو حفظ حالة المعطى ebp عمل pushl %ebp, ، من الضروري الوظيفة التي تجعل المكالمة، ومن استبدالها بموقف المكدس الحالي esp عمل movl %esp, %ebp. وبعد تصفية آخر 4 بت من ebp في هذه المرحلة هو محددة دول مجلس التعاون الخليجي، لا أعرف لماذا هذا التحويل البرمجي يفعل ذلك. سيعمل دون القيام بذلك. الآن أخيرا نذهب إلى العمل، call ___main, من هو __main؟ أنا لا أعرف إما ... ربما أكثر إجراءات محددة من دول مجلس التعاون الخليجي، وأخيرا الشيء الوحيد الخاص بك الرئيسي ()، تعيين قيمة الإرجاع كما 0 مع movl $0, %eax و leave وهو نفسه كما تفعل movl %ebp, %esp; popl %ebp لاستعادة ebp الدولة، إذن ret لانهاء. ret الملوثات العضوية الثابتة eip ومواصلة تدفق الخيط من تلك النقطة، أينما كان (كما هو الرئيسي ()، فإن هذا الرعيد يؤدي إلى بعض إجراءات النواة التي تعالج نهاية البرنامج).

معظم كل شيء يدور حول إدارة المكدس. كتبت برنامج تعليمي مفصل حول كيفية استخدام المكدس منذ بعض الوقت، سيكون من المفيد شرح سبب صنع كل هذه الأشياء. لكن في البرتغالية ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top