إنشاء آلة ممر المحاكي. الجزء 2

الصورة

الجزء الأول هنا .

8080 معالج تفكيك


التعارف


سنحتاج إلى معلومات حول رموز opcodes وأوامر كل منها. عندما تبحث عن معلومات على الإنترنت ، ستلاحظ أن هناك الكثير من المعلومات المختلطة حول 8080 و Z80. كان Z80 تابعًا لـ 8080 - فهو ينفذ جميع تعليمات 8080 بنفس الرموز السداسية ، ولكن لديه أيضًا تعليمات إضافية. أعتقد أنه في حين يجب عليك تجنب المعلومات حول Z80 ، حتى لا يتم الخلط. لقد قمت بإنشاء جدول opcode لعملنا ، إنه هنا .

يحتوي كل معالج على دليل مرجعي مكتوب من قبل الشركة المصنعة. عادة ما يطلق عليه شيء مثل "دليل البيئة للمبرمجين". يُسمى دليل 8080 دليل مستخدم أنظمة Intel 8080 للحواسيب الصغيرة. لطالما كان يطلق عليه "دفتر البيانات" ، لذلك سأطلق عليه أيضًا. تمكنت من تنزيل مرجع 8080 من http://www.datasheetarchive.com/ . يعد PDF هذا مسحًا ضوئيًا منخفض الجودة ، لذلك إذا وجدت إصدارًا أفضل ، فاستخدمه.

لنبدأ ونلقي نظرة على ROM Invaders ROM. (يمكن العثور على ملف ROM على الإنترنت.) أعمل على نظام التشغيل Mac OS X ، لذلك أستخدم الأمر hexdump فقط لعرض محتوياته. لمزيد من العمل ، ابحث عن محرر ست عشري لمنصتك. فيما يلي أول 128 بايت من ملف invaders.h:

$ hexdump -v invaders.h 0000000 00 00 00 c3 d4 18 00 00 f5 c5 d5 e5 c3 8c 00 00 0000010 f5 c5 d5 e5 3e 80 32 72 20 21 c0 20 35 cd cd 17 0000020 db 01 0f da 67 00 3a ea 20 a7 ca 42 00 3a eb 20 0000030 fe 99 ca 3e 00 c6 01 27 32 eb 20 cd 47 19 af 32 0000040 ea 20 3a e9 20 a7 ca 82 00 3a ef 20 a7 c2 6f 00 0000050 3a eb 20 a7 c2 5d 00 cd bf 0a c3 82 00 3a 93 20 0000060 a7 c2 82 00 c3 65 07 3e 01 32 ea 20 c3 3f 00 cd 0000070 40 17 3a 32 20 32 80 20 cd 00 01 cd 48 02 cd 13 ... 

هذه هي بداية برنامج Space Invaders. كل رقم سداسي عشري هو أمر أو بيانات للبرنامج. يمكننا استخدام مرجع أو معلومات مرجعية أخرى لفهم ما تعنيه هذه الرموز السداسية. دعنا نستكشف رمز صورة ROM أكثر قليلاً.

البايت الأول من هذا البرنامج هو 00 دولار. بالنظر إلى الجدول ، نرى أنه NOP ، بالإضافة إلى الأمرين التاليين. (ولكن لا تثبط عزيمتك ، ربما استخدم غزاة الفضاء هذه الأوامر كتأخير للسماح للنظام بالهدوء قليلاً بعد تشغيل الطاقة.)

الأمر الرابع هو $ C3 ، أي إذا حكمنا من خلال الجدول ، هذا هو JMP. يشير تعريف أمر JMP إلى أنه يتلقى عنوانًا ثنائي البايت ، أي أن البايتان التاليان هما عنوان قفزة JMP. ثم يأتي اثنان من NOPs ... لذا ، أتعلمون؟ دعني أوقع التعليمات القليلة الأولى بنفسي ...

  0000 00 NOP 0001 00 NOP 0002 00 NOP 0003 c3 d4 18 JMP $18d4 0006 00 NOP 0007 00 NOP 0008 f5 PUSH PSW 0009 c5 PUSH B 000a d5 PUSH D 000b e5 PUSH H 000c c3 8c 00 JMP $008c 000f 00 NOP 0010 f5 PUSH PSW 0011 c5 PUSH B 0012 d5 PUSH D 0013 e5 PUSH H 0014 3e 80 MVI A,#0x80 0016 32 72 20 STA $2072 

يبدو أن هناك طريقة ما لأتمتة هذه العملية ...

المجمع ، الجزء 1


المفكك هو برنامج يقوم ببساطة بترجمة دفق من الأرقام السداسية مرة أخرى إلى التعليمات البرمجية المصدر بلغة التجميع. هذه هي المهمة التي قمنا بها يدويًا في القسم السابق - وهي فرصة رائعة لأتمتة هذا العمل. عند كتابة هذا الجزء من التعليمات البرمجية ، نتعرف على المعالج ونحصل على قطعة مناسبة من كود تصحيح الأخطاء ، وهو أمر مفيد عند كتابة محاكي وحدة المعالجة المركزية.

إليك خوارزمية فك شفرة 8080:

  1. قراءة التعليمات البرمجية في المخزن المؤقت
  2. نحصل على مؤشر في بداية المخزن المؤقت
  3. استخدم البايت في المؤشر لتحديد كود التشغيل.
  4. اعرض اسم كود التشغيل ، إذا لزم الأمر باستخدام وحدات البايت بعد كود التشغيل كبيانات
  5. انقل المؤشر إلى عدد البايتات التي يستخدمها هذا الأمر (1 أو 2 أو 3 بايت)
  6. إذا لم ينتهي المخزن المؤقت ، فانتقل إلى الخطوة 3

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

  /* *codebuffer -       8080 pc -          */ int Disassemble8080Op(unsigned char *codebuffer, int pc) { unsigned char *code = &codebuffer[pc]; int opbytes = 1; printf ("%04x ", pc); switch (*code) { case 0x00: printf("NOP"); break; case 0x01: printf("LXI B,#$%02x%02x", code[2], code[1]); opbytes=3; break; case 0x02: printf("STAX B"); break; case 0x03: printf("INX B"); break; case 0x04: printf("INR B"); break; case 0x05: printf("DCR B"); break; case 0x06: printf("MVI B,#$%02x", code[1]); opbytes=2; break; case 0x07: printf("RLC"); break; case 0x08: printf("NOP"); break; /* ........ */ case 0x3e: printf("MVI A,#0x%02x", code[1]); opbytes = 2; break; /* ........ */ case 0xc3: printf("JMP $%02x%02x",code[2],code[1]); opbytes = 3; break; /* ........ */ } printf("\n"); return opbytes; } 

في عملية كتابة هذا الإجراء ودراسة كل رمز تشغيل ، تعلمت الكثير عن معالج 8080.

  1. أدركت أن معظم الفرق تأخذ بايت واحد ، والباقي اثنان أو ثلاثة. يفترض الكود أعلاه أن الأمر هو بايت واحد في الحجم ، لكن التعليمات ثنائية وثلاث بايت تغير قيمة متغير "opbytes" بحيث يتم إرجاع الحجم الصحيح للأمر.
  2. يحتوي 8080 على سجلات بأسماء A و B و C و D و E و H و L. وهناك أيضًا عداد برامج (عداد برامج ، كمبيوتر) ومؤشر مكدس منفصل (مؤشر مكدس ، SP).
  3. تعمل بعض الإرشادات مع السجلات في أزواج: B و C زوج ، وكذلك DE و HL.
  4. A هو سجل خاص ، العديد من التعليمات تعمل معه.
  5. HL هو أيضًا سجل خاص ، يتم استخدامه كعنوان لكل قراءة وكتابة للبيانات في الذاكرة.
  6. شعرت بالفضول حيال فريق "RST" ، لذا قرأت الدليل قليلاً. لقد لاحظت أنه ينفذ التعليمات البرمجية في أماكن ثابتة ويشار إلى الإشارة المرجعية معالجة المقاطعة. بعد مزيد من القراءة ، اتضح أن كل هذا الرمز في بداية ROM كان إجراءات خدمة المقاطعة (ISRs). يمكن إنشاء المقاطعات برمجياً باستخدام الأمر RST ، أو يتم إنشاؤها بواسطة مصادر خارجية (وليس معالج 8080).

لتحويل كل هذا إلى برنامج عمل ، قمت للتو بإعداد إجراء يقوم بالخطوات التالية:

  1. يفتح ملفًا مليئًا بالرمز المتراكم 8080
  2. يقرأه إلى المخزن المؤقت للذاكرة
  3. يمر خلال المخزن المؤقت للذاكرة ، مما تسبب في Disassemble8080Op
  4. يزيد جهاز الكمبيوتر الذي تم إرجاعه بواسطة Disassemble8080Op
  5. يخرج في نهاية المخزن المؤقت

قد يبدو شيء مثل هذا:

  int main (int argc, char**argv) { FILE *f= fopen(argv[1], "rb"); if (f==NULL) { printf("error: Couldn't open %s\n", argv[1]); exit(1); } //         fseek(f, 0L, SEEK_END); int fsize = ftell(f); fseek(f, 0L, SEEK_SET); unsigned char *buffer=malloc(fsize); fread(buffer, fsize, 1, f); fclose(f); int pc = 0; while (pc < fsize) { pc += Disassemble8080Op(buffer, pc); } return 0; } 

في الجزء الثاني ، سوف نقوم بفحص المخرجات التي تم الحصول عليها عن طريق تفكيك الغزاة ROM الفضاء.

تخصيص الذاكرة


قبل أن نبدأ في كتابة محاكي معالج ، نحتاج إلى دراسة جانب آخر. جميع وحدات المعالجة المركزية لديها القدرة على التواصل مع عدد معين من العناوين. تحتوي المعالجات القديمة على عناوين 16 أو 24 أو 32 بت. يحتوي 8080 على 16 عنوان اتصال ، لذا فإن العناوين تقع في نطاق 0- $ FFFF.

لفهم تخصيص ذاكرة اللعبة ، نحتاج إلى إجراء تحقيق صغير. بعد جمع أجزاء من المعلومات هنا وهنا ، اكتشفت أن ROM موجود في العنوان 0 ، ولدى اللعبة 8 كيلوبايت من ذاكرة الوصول العشوائي بدءًا من 2000 دولار.

اكتشف مؤلف إحدى الصفحات أن مخزن الفيديو المؤقت يبدأ في ذاكرة الوصول العشوائي بعنوان 2،400 دولار ، وأخبرنا أيضًا عن كيفية استخدام 8080 منفذ إدخال وإخراج للتواصل مع عناصر التحكم وأجهزة الصوت. عظيم!

داخل ملف ROM invaders.zip ، الذي يمكن العثور عليه على الإنترنت ، هناك أربعة ملفات: invaders.e و. f و. g و. h. بعد googling ، صادفت مقالة غنية بالمعلومات تخبرنا عن كيفية وضع هذه الملفات في الذاكرة:

Space Invaders, (C) Taito 1978, Midway 1979

: Intel 8080, 2 ( Zilog Z80)

: $cf (RST 8) vblank, $d7 (RST $10) vblank.

: 256(x)*224(y), 60 , .
.
: 7168 , 1 (32 ).

: SN76477 .

:
ROM
$0000-$07ff: invaders.h
$0800-$0fff: invaders.g
$1000-$17ff: invaders.f
$1800-$1fff: invaders.e

RAM
$2000-$23ff:
$2400-$3fff:

$4000-:


لا تزال هناك بعض المعلومات المفيدة ، لكننا لسنا مستعدين لاستخدامها بعد.

تفاصيل دموية


إذا كنت تريد معرفة حجم مساحة العنوان التي يحتوي عليها المعالج ، فيمكنك فهم ذلك من خلال النظر في خصائصه. تخبرنا المواصفة 8080 أن المعالج يحتوي على 16 عنوان اتصال ، أي أنه يستخدم عنونة 16 بت. (بدلاً من المواصفات ، يكفي قراءة الدليل ، Wikipedia ، google ، وما إلى ذلك ...)

على الإنترنت هناك الكثير من المعلومات حول أجهزة Space Invaders. إذا لم تتمكن من العثور على هذه المعلومات ، يمكنك الحصول عليها بطريقتين:

  • شاهد الكود الذي يعمل في المحاكي واكتشف ما يفعله. تدوين الملاحظات ومشاهدتها بعناية. يجب أن تكون بسيطة بما يكفي لفهم ، على سبيل المثال ، حيث ، في رأي اللعبة ، يجب أن تكون ذاكرة الوصول العشوائي. من السهل أيضًا تحديد المكان الذي تبحث فيه عن ذاكرة الفيديو (سنقضي بعض الوقت في دراسة ذلك).
  • ابحث عن مخطط الدائرة لآلة الممرات وتتبع الإشارات من جهات اتصال العنوان لوحدة المعالجة المركزية. انظر إلى أين يذهبون. على سبيل المثال ، يمكن أن تذهب A15 (العنوان الأقدم) إلى ROM فقط. من هذا يمكننا أن نستنتج أن عناوين ROM تبدأ من 8000 دولار.

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

تطوير سطر الأوامر


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

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

أعتقد أن أي شخص يريد البرمجة على مستوى منخفض يجب أن يعرف كيفية إنشاء برامج بسيطة من سطر الأوامر. قد تفكر في أنني أزعجك ، لكن مهاراتك في مجال القراصنة لا تستحق الكثير إذا لم تتمكن من العمل خارج Visual Studio.

في نظام التشغيل Mac ، يمكنك استخدام TextEdit و Terminal للترجمة. في Linux ، يمكنك استخدام gedit و Konsole. في Windows ، يمكنك تثبيت cygwin والأدوات ، ثم استخدام N ++ أو محرر نصوص آخر. إذا كنت تريد أن تكون رائعًا حقًا ، فإن جميع هذه الأنظمة الأساسية تدعم vi و emacs لتحرير النص.

تجميع البرامج من ملف واحد باستخدام سطر الأوامر مهمة تافهة. افترض أنك قمت بحفظ البرنامج في ملف يسمى 8080dis.c . انتقل إلى المجلد الذي يحتوي على هذا الملف النصي وقم cc 8080dis.c : cc 8080dis.c . إذا لم تحدد اسم ملف الإخراج ، فسيتم تسميته a.out ، ويمكنك تشغيله بكتابة ./a.out .

هذا ، في الواقع ، كل شيء.

باستخدام المصحح


إذا كنت تعمل على أحد الأنظمة المستندة إلى Unix ، فإليك مقدمة موجزة لتصحيح أخطاء برامج سطر الأوامر باستخدام GDB. أنت بحاجة إلى تجميع البرنامج مثل هذا: cc -g -O0 8080dis.c . يقوم -g بإنشاء معلومات تصحيح الأخطاء (أي يمكنك إجراء التصحيح بناءً على النص المصدر) ، -O0 بتعطيل التحسينات حتى عندما -O0 عبر البرنامج ، يستطيع المصحح تتبع التعليمات البرمجية بدقة بما يتوافق تمامًا مع النص المصدر.

فيما يلي السجل المشروح لبدء جلسة تصحيح الأخطاء. تعليقاتي في الأسطر المميزة بعلامة الجنيه (#).

  $ gdb a.out GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug 8 20:32:45 UTC 2011) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done #  ,       (gdb) b Disassemble8080Op Breakpoint 1 at 0x1000012ef: file 8080dis.c, line 7. #   "invaders.h"    (gdb) run invaders.h Starting program: /Users/bob/Desktop/invaders/a.out invaders.h Reading symbols for shared libraries +........................ done Breakpoint 1, Disassemble8080Op (codebuffer=0x100801000 "", pc=0) at 8080dis.c:7 7 unsigned char *code = &codebuffer[pc]; #gdb  n  "next".    "next" (gdb) n 8 int opbytes = 1; #p -    "print",     *code (gdb) p *code $1 = 0 '\0' (gdb) n 9 printf("%04x ", pc); #    "", gdb     ,    "next" (gdb) 10 switch (*code) (gdb) n #   ,    "NOP" 12 case 0x00: printf("NOP"); break; (gdb) n 285 printf("\n"); #c -  "continue",        (gdb) c Continuing. 0000 NOP #     Disassemble8080Op.   *opcode, # ,      NOP,    . Breakpoint 1, Disassemble8080Op (codebuffer=0x100801000 "", pc=1) at 8080dis.c:7 7 unsigned char *code = &codebuffer[pc]; (gdb) c Continuing. 0001 NOP Breakpoint 1, Disassemble8080Op (codebuffer=0x100801000 "", pc=2) at 8080dis.c:7 7 unsigned char *code = &codebuffer[pc]; (gdb) n 8 int opbytes = 1; (gdb) p *code $2 = 0 '\0' #  NOP,   (gdb) c Continuing. 0002 NOP Breakpoint 1, Disassemble8080Op (codebuffer=0x100801000 "", pc=3) at 8080dis.c:7 7 unsigned char *code = &codebuffer[pc]; (gdb) n 8 int opbytes = 1; #   ! (gdb) p *code $3 = 195 '?' # print     ,    /x    (gdb) p /x *code $4 = 0xc3 (gdb) n 9 printf("%04x ", pc); (gdb) 10 switch (*code) (gdb) # C3 -  JMP. . 219 case 0xc3: printf("JMP $%02x%02x",code[2],code[1]); opbytes = 3; break; (gdb) 285 printf("\n"); 

المجمع ، الجزء 2


قم بتشغيل أداة التفكيك لملف ROM invaders.h وانظر إلى المعلومات المعروضة.

  0000 NOP 0001 NOP 0002 NOP 0003 JMP $18d4 0006 NOP 0007 NOP 0008 PUSH PSW 0009 PUSH B 000a PUSH D 000b PUSH H 000c JMP $008c 000f NOP 0010 PUSH PSW 0011 PUSH B 0012 PUSH D 0013 PUSH H 0014 MVI A,#$80 0016 STA $2072 0019 LXI H,#$20c0 001c DCR M 001d CALL $17cd 0020 IN #$01 0022 RRC 0023 JC $0067 0026 LDA $20ea 0029 ANA A 002a JZ $0042 002d LDA $20eb 0030 CPI #$99 0032 JZ $003e 0035 ADI #$01 0037 DAA 0038 STA $20eb 003b CALL $1947 003e SRA A 003f STA $20ea /* 0000000 00 00 00 c3 d4 18 00 00 f5 c5 d5 e5 c3 8c 00 00 0000010 f5 c5 d5 e5 3e 80 32 72 20 21 c0 20 35 cd cd 17 0000020 db 01 0f da 67 00 3a ea 20 a7 ca 42 00 3a eb 20 0000030 fe 99 ca 3e 00 c6 01 27 32 eb 20 cd 47 19 af 32 */ 

تتوافق التعليمات الأولى مع تلك التي كتبناها يدويًا في وقت سابق. بعدها هناك عدة تعليمات جديدة. لقد أدرجت أدناه بيانات سداسية للرجوع إليها. لاحظ أنه إذا قارنت الذاكرة بالأوامر ، فستكون العناوين كما لو كانت مخزنة في الذاكرة بالترتيب العكسي. هكذا هي. وهذا ما يسمى بـ endian الصغير - فالآلات ذات endian الصغير ، مثل 8080 ، تقوم بتخزين البايت الأقل أهمية من الأرقام أولاً. (المزيد عن endian موصوف أدناه.)

ذكرت أعلاه أن هذا الرمز هو رمز ISR للعبة Space Invaders. يبدأ رمز المقاطعات 0 ، 1 ، 2 ، ... 7 بالعنوان $ 0 ، $ 8 ، $ 20 ، ... $ 38. يبدو أن 8080 يعطي 8 بايت فقط لكل ISR. في بعض الأحيان يتجاوز برنامج Space Invaders هذا النظام بمجرد الانتقال إلى عنوان آخر بمساحة أكبر. (يحدث هذا عند $ 000c).

بالإضافة إلى ذلك ، يبدو أن ISR 2 أطول من الذاكرة المخصصة له. يذهب رمزها إلى $ 0018 (هذا هو المكان لـ ISR 3). أعتقد أن Space Invaders لا يتوقعون رؤية أي شيء يستخدم المقاطعة 3.

يتكون ملف ROM غزاة الفضاء من الإنترنت من أربعة أجزاء. سأشرح هذا أدناه ، ولكن الآن ، للانتقال إلى القسم التالي ، نحتاج إلى دمج هذه الملفات الأربعة في ملف واحد. على يونكس:

  cat invaders.h > invaders cat invaders.g >> invaders cat invaders.f >> invaders cat invaders.e >> invaders 

الآن قم بتشغيل أداة التفكيك مع ملف "الغزاة" الناتج. عندما يبدأ البرنامج بسعر $ 0000 ، فإن أول شيء يفعله هو التبديل إلى $ 18d4. سأعتبر هذا بداية البرنامج. دعنا نلقي نظرة سريعة على هذا الرمز.

  18d4 LXI SP,#$2400 18d7 MVI B,#$00 18d9 CALL $01e6 

لذا ، ينفذ عمليتين ويستدعي 01e6 دولارًا. سأقوم بإدراج جزء من الكود مع التحولات في هذا الكود:

  01e6 LXI D,#$1b00 01e9 LXI H,#$2000 01ec JMP $1a32 ..... 1a32 LDAX D 1a33 MOV M,A 1a34 INX H 1a35 INX D 1a36 DCR B 1a37 JNZ $1a32 1a3a RET 

كما رأينا من تخصيص ذاكرة غزاة الفضاء ، فإن بعض هذه العناوين مثيرة للاهتمام. 2000 دولار هو بداية برنامج "RAM RAM العامل". 2400 دولار هي بداية ذاكرة الفيديو.

دعنا نضيف تعليقات إلى الكود لشرح ما يفعله مباشرة عند بدء التشغيل:

  18d4 LXI SP,#$2400 ; SP=$2400 -      18d7 MVI B,#$00 ; B=0 18d9 CALL $01e6 ..... 01e6 LXI D,#$1b00 ; DE=$1B00 01e9 LXI H,#$2000 ; HL=$2000 01ec JMP $1a32 ..... 1a32 LDAX D ; A = (DE),   ,       $1B00 1a33 MOV M,A ;  A  (HL),     $2000 1a34 INX H ; HL = HL + 1 ( $2001) 1a35 INX D ; DE = DE + 1 ( $1B01) 1a36 DCR B ; B = B - 1 ( 0xff,      0) 1a37 JNZ $1a32 ; ,   ,     b=0 1a3a RET 

يبدو أن هذا الرمز سينسخ 256 بايت من $ 1b00 إلى $ 2000. لماذا؟ لا اعرف. يمكنك دراسة البرنامج بمزيد من التفصيل والتفكير في ما يفعله.

هناك مشكلة هنا. إذا كان لدينا قطعة عشوائية من الذاكرة تحتوي على رمز ، فمن المحتمل أن تتناوب البيانات معها.

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

بينما لا يمكننا فعل أي شيء حيال ذلك. فقط ضع في اعتبارك أن مثل هذه المشكلة موجودة. إذا رأيت شيئًا كهذا:

  • الانتقال من رمز جيد تمامًا إلى فريق غير مدرج في قائمة أداة التفكيك
  • دفق رمز لا معنى له (مثل POP B POP B POP B POP C XTHL XTHL XTHL)

هنا ، على الأرجح ، هناك بيانات دمرت بعض الشفرات المفككة. إذا حدث هذا ، فأنت بحاجة إلى البدء مرة أخرى من الإزاحة.

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

يمكن الاطلاع على تحليل مفصل لرمز غزاة الفضاء هنا .

إنديان


يتم تخزين وحدات البايت بشكل مختلف في نماذج المعالج المختلفة ، ويعتمد التخزين على حجم البيانات. تخزن الآلات الكبيرة النهاية البيانات من الأقدم إلى الأصغر. يبقيهم القليل من الإنديين من الأصغر إلى الأكبر. إذا تمت كتابة عدد صحيح 32 بت 0xAABBCCDD على ذاكرة كل جهاز ، فسيبدو كما يلي:

في النهاية الصغيرة: $ DD $ CC $ BB $ AA

Big-endian: $ AA $ BB $ CC $ DD

لقد بدأت البرمجة على معالجات Motorola التي تستخدم endian-endian ، لذلك بدا لي أكثر "طبيعية" ، ولكن بعد ذلك اعتدت على Endian الصغير أيضًا.

يتفكك جهاز التفكيك والمحاكي الخاص بي تمامًا مشكلة الإنديان لأنهم يقرؤون بايت واحد فقط في كل مرة. إذا كنت تريد ، على سبيل المثال ، استخدام قارئ 16 بت لقراءة العنوان من ROM ، فلاحظ أن هذا الرمز غير قابل للنقل بين بنى وحدة المعالجة المركزية.

Source: https://habr.com/ru/post/ar418683/


All Articles