سؤال

أحاول تعلم التجميع من الصفر. لقد قرأت قليلاً ، لكن حتى البرنامج البسيط التالي الذي وجدته في كتاب مرجعي قد صعدني:

section .data
msg db "Hello!", 0xa
len equ $ - msg
section .text

     global _start

_start:


move edx, len
move ecx, msg
move ebx, 1
move eax, 4
int  0x80
move ebx, 0
move eax, 1
int 0x80

يبدو أن هذا من المفترض أن يطبع هذا "مرحبًا". لكني لا أعرف حتى ما يحدث في أي من المراحل. وضعت المرحلتان الأوليان طول الرسالة والسيطات في سجلين ، لم يتم استخدامها مرة أخرى. أنا لا أفهم لماذا.

لا أعرف لماذا هناك حاجة إلى أربعة سجلات مختلفة.

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

المحلول

int 80 هي آلية في بعض أنظمة التشغيل التي تشبه UNIX لإجراء مكالمات النظام.

لهذه المكالمات ، يتم استخدام السجلات لقيم محددة. من syscalls ملف:

0 STD NOHIDE { int nosys(void); } syscall nosys_args int
1 STD NOHIDE { void exit(int rval); } exit rexit_args void
2 STD POSIX  { int fork(void); }
3 STD POSIX  { ssize_t read(int fd, void *buf, size_t nbyte); }
4 STD POSIX  { ssize_t write(int fd, const void *buf, size_t nbyte); }

يمكنك رؤية أن الرقم 4 هو write اتصل وتحتاج إلى ثلاثة معلمات أخرى. رقم 1 هو exit ويحتاج فقط رمز الإرجاع.

عند إجراء المكالمة ، eax هو syscall الذي تصنعه أثناء ebx, ecx و edx هي المعلمات الثلاثة (على افتراض أنها جميعها مطلوبة - exit على سبيل المثال لا يحتاج سوى واحد).

لذلك ، يمكنك التعليق على الرمز على النحو التالي:

move edx, len   ; length of message (nbyte).
move ecx, msg   ; message to print (buf).
move ebx, 1     ; file handle 1, stdout (fd).
move eax, 4     ; write syscall.
int  0x80       ; do it.

move ebx, 0     ; exit code (rval).
move eax, 1     ; exit syscall.
int 0x80        ; do it.

*أ: قدمت الإصدارات اللاحقة من Linux واجهة جديدة يمكنها استخدام طرق مختلفة بناءً على أفضل سرعة. على سبيل المثال ، بعض رقائق Intel أسرع بكثير إذا كنت تستخدم sysenter عوضا عن int 80.

نصائح أخرى

IIRC int 0x80 يتم استخدام التعليمات لاستدعاء syscall باستخدام متجه المقاطعة. في مثالك القيم في ebx و eax تستخدم لتحديد أي syscall سوف تتصل (ربما عملية الطباعة على stdout).

يعرف Syscall عن طريق القبول edx و ecx يجب أن تحتوي على ما سيتم طباعته.

على العديد من الأنظمة ، int 80h هل استدعاء النظام بوابة. رقم Syscall في eax. ebx, ecx و edx تحتوي على معلمات إضافية:

move edx, len
move ecx, msg
move ebx, 1    ; fd 1 is stdout
move eax, 4    ; syscall 4 is write
int  0x80      ; write(1, msg, len)
move ebx, 0
move eax, 1    ; syscall 1 is exit
int 0x80       ; exit(0)

عند استدعاء مكالمة النظام ، "int" ذاكري ، يتم إنشاء انقطاع النظام. إنه "يقفز" كيندا إلى وظيفة النظام ، والتي ، في هذه الحالة ، تطبع الإخراج (يعتمد على EAX).

يستخدم هذا الانقطاع كل هذه السجلات لمعرفة ما يجب القيام به. تقرأ المقاطعة EAX ، تحقق من الوظيفة التي تريدها وتستخدم السجلات الأخرى للقيام بذلك.

EAX هو رقم الوظيفة ، 4 يعني sys_write ، الذي يكتب سلسلة إلى واصف دفق/ملف.

الآن تعرف أنك تريد كتابة شيء ما إلى مكان ما ، ثم يستخدم السجلات الأخرى لتلك المعلومات.

بالنسبة إلى EAX = 4 و int 0x80 ، هذا هو المعنى للسجلات الأخرى:

EBX = الإخراج (1 = stdout)
ECX = عنوان السلسلة
edx = طول السلسلة

يمكنك قراءة هذا:

http://www.intel.com/assets/ja_jp/pdf/manual/253665.pdf

القسم 6.4 لديه بعض الأشياء حول المقاطعات والاستثناءات.

ويمكنك البدء في كتابة رمز تجميع Intel 80x86 ، وهو أبسط وأسهل في الفهم ، إليك بعض الروابط:

Mnemonics/Code Tables Cheatsheet:http://www.jegerlehner.ch/intel/

بعض مواقع المقدمة:http://mysite.du.edu/~etuttle/math/8086.htmhttp://www.malware.org/teaching/assembly.htm

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