Little Man Computer

The Little Man Computer (LMC) is an instructional model of a computer, created by Dr. Stuart Madnick in 1965.[1] The LMC is generally used to teach students, because it models a simple von Neumann architecture computer—which has all of the basic features of a modern computer. It can be programmed in machine code (albeit in decimal rather than binary) or assembly code.[2][3][4]
The LMC model is based on the concept of a little man shut in a closed mail room (analogous to a computer in this scenario). At one end of the room, there are 100 mailboxes (memory), numbered 0 to 99, that can each contain a 3 digit instruction or data (ranging from 000 to 999). Furthermore, there are two mailboxes at the other end labeled INBOX and OUTBOX which are used for receiving and outputting data. In the center of the room, there is a work area containing a simple two function (addition and subtraction) calculator known as the Accumulator and a resettable counter known as the program counter. The program counter holds the address of the next instruction the Little Man will carry out. This program counter is normally incremented by 1 after each instruction is executed, allowing the Little Man to work through a program sequentially. Branch instructions allow iteration (loops) and conditional programming structures to be incorporated into a program. The latter is achieved by setting the program counter to a non-sequential memory address if a particular condition is met (typically the value stored in the accumulator being zero or positive).
As specified by the von Neumann architecture, any mailbox (signifying a unique memory location) can contain either an instruction or data. Care therefore needs to be taken to stop the program counter from reaching a memory address containing data - or the Little Man will attempt to treat it as an instruction. One can take advantage of this by writing instructions into mailboxes that are meant to be interpreted as code, to create self-modifying code. To use the LMC, the user loads data into the mailboxes and then signals the Little Man to begin execution, starting with the instruction stored at memory address zero. Resetting the program counter to zero effectively restarts the program, albeit in a potentially different state.
Execution cycle
To execute a program, the little man performs these steps:
- تحقق من عداد البرنامج لمعرفة رقم صندوق البريد الذي يحتوي على تعليمات البرنامج (أي صفر في بداية البرنامج).
- استرجع التعليمات من صندوق البريد الذي يحمل هذا الرقم. تحتوي كل تعليمات على حقلين: رمز العملية (الذي يشير إلى العملية المراد تنفيذها) وحقل العنوان (الذي يشير إلى مكان العثور على البيانات المراد تنفيذ العملية عليها).
- قم بزيادة عداد البرنامج (بحيث يحتوي على رقم صندوق البريد للتعليمات التالية)
- فك تشفير التعليمات. إذا كانت التعليمات تستخدم بيانات مخزنة في صندوق بريد آخر، فاستخدم حقل العنوان للعثور على رقم صندوق البريد الخاص بالبيانات التي ستعمل عليها، على سبيل المثال "الحصول على البيانات من صندوق البريد 42".
- استرجاع البيانات (من المدخلات أو المجمع أو صندوق البريد الذي تم تحديد عنوانه في الخطوة 4)
- نفّذ التعليمات بناءً على رمز العملية المُعطى
- قم بتفرع أو تخزين النتيجة (في المخرجات أو المجمع أو صندوق البريد بالعنوان المحدد في الخطوة 4)
- ارجع إلى عداد البرنامج لتكرار الدورة أو إيقافها
الأوامر
على الرغم من أن LMC يعكس العمليات الفعلية للمعالجات الثنائية ، فقد تم اختيار بساطة الأرقام العشرية لتقليل التعقيد للطلاب الذين قد لا يشعرون بالراحة في العمل بالنظام الثنائي / الست عشري .
تعليمات
تُبرمج بعض محاكيات LMC مباشرةً باستخدام تعليمات رقمية مكونة من ثلاثة أرقام، بينما تستخدم أخرى رموزًا وعلامات تذكيرية مكونة من ثلاثة أحرف. في كلتا الحالتين، تكون مجموعة التعليمات محدودة للغاية عمدًا (عادةً حوالي عشر تعليمات) لتبسيط الفهم. إذا استخدم محاكي LMC رموزًا وعلامات تذكيرية، فسيتم تحويلها إلى تعليمات رقمية مكونة من ثلاثة أرقام عند تجميع البرنامج.
يوضح الجدول أدناه مجموعة تعليمات رقمية نموذجية ورموز التذكير المكافئة لها.
| الرمز الرقمي | رمز التذكر | تعليمات | وصف |
|---|---|---|---|
| 1xx | يضيف | يضيف | أضف القيمة المخزنة في صندوق البريد xx إلى أي قيمة موجودة حاليًا في المُجمِّع (الآلة الحاسبة).
|
| 2xx | فرعي | طرح | اطرح القيمة المخزنة في صندوق البريد xx من أي قيمة موجودة حاليًا في المُجمِّع (الآلة الحاسبة).
|
| 3xx | STA | محل | قم بتخزين محتويات المُجمِّع في صندوق البريد xx (مدمر).
|
| 5xx | LDA | حمولة | قم بتحميل القيمة من صندوق البريد xx (غير مدمر) وأدخلها في المُجمِّع (مدمر). |
| 6xx | حمالة صدر | الفرع دائماً (بدون شروط) | قم بتعيين عداد البرنامج إلى العنوان المحدد (القيمة xx). أي أن القيمة الموجودة في صندوق البريد xx ستكون هي التعليمات التالية التي سيتم تنفيذها. |
| 7xx | BRZ | تفرع إذا كان الصفر ( شرطي ) | إذا كانت قيمة المُجمِّع (الحاسبة) تساوي 000، فاضبط عداد البرنامج على القيمة xx. وإلا، فلا تفعل شيئًا. يبقى تأثير علامة السالب غير مُحدد. عند حدوث تجاوز في قيمة المُجمِّع نتيجةً لعملية الطرح، يتم ضبط هذه العلامة، وبعدها تصبح قيمة المُجمِّع غير مُحددة، وقد تصل إلى الصفر، مما يجعل سلوك BRZ غير مُحدد عند حدوث التجاوز. السلوك المُقترح هو التفرع إذا كانت قيمة المُجمِّع صفرًا ولم يتم ضبط علامة السالب.
|
| 8xx | بطاقة الإقامة الدائمة | تفرع إذا كانت النتيجة إيجابية (مشروطة) | إذا كانت قيمة المُجمِّع (الحاسبة) تساوي صفرًا أو موجبة، فاضبط عداد البرنامج على القيمة xx. وإلا، فلا تفعل شيئًا. بما أن خلايا ذاكرة LMC لا يمكنها استيعاب سوى قيم بين 0 و999، فإن هذه التعليمة تعتمد كليًا على علامة السالب التي يتم ضبطها بسبب تجاوز الحد الأدنى في عملية الطرح، وربما على تجاوز الحد الأقصى في عملية الجمع (غير مُعرَّف).
|
| 901 | INP | مدخل | انتقل إلى صندوق الوارد، واحصل على القيمة من المستخدم، وضعها في المُجمِّع (الآلة الحاسبة).
|
| 902 | خارج | الناتج | انسخ القيمة من المُجمِّع (الآلة الحاسبة) إلى صندوق الإخراج.
|
| ٠٠٠ | HLT/COB | استراحة/استراحة قهوة | توقف عن العمل/أنهِ البرنامج. |
| بيانات | بيانات | هذه تعليمة تجميعية تحجز صندوق بريد لتخزين البيانات. يمكن إعطاؤها رقمًا للتخزين في بداية البرنامج، على سبيل المثال، DAT 984 سيخزن القيمة 984 في صندوق بريد على عنوان تعليمة DAT. يمكن أيضًا استخدام DAT مع التسميات لتعريف المتغيرات. |
أمثلة
استخدام رموز التعليمات الرقمية (شفرة الآلة)
هذا البرنامج (من التعليمات 901 إلى التعليمات 000 ) مكتوب باستخدام الرموز الرقمية فقط. يأخذ البرنامج رقمين كمدخلات ويُخرج الفرق بينهما. لاحظ أن التنفيذ يبدأ من صندوق البريد 00 وينتهي عند صندوق البريد 07. فيما يلي شرحٌ لعيوب برمجة وحدة التحكم المنطقية القابلة للبرمجة (LMC) باستخدام رموز التعليمات الرقمية.
| صندوق البريد | الرمز الرقمي | عملية | تعليقات |
|---|---|---|---|
| ٠٠ | 901 | المُجمِّع = صندوق الوارد | أدخل الرقم الأول في الآلة الحاسبة (مع مسح أي شيء كان موجوداً). |
| 01 | 308 | صندوق البريد 08 = المُجمِّع | قم بتخزين القيمة الحالية للآلة الحاسبة (للتحضير للخطوة التالية...) |
| 02 | 901 | المُجمِّع = صندوق الوارد | أدخل الرقم الثاني في الآلة الحاسبة (مع مسح أي شيء كان موجوداً هناك). |
| 03 | 309 | صندوق البريد 09 = المُجمِّع | قم بتخزين القيمة الحالية للآلة الحاسبة (مرة أخرى، استعدادًا للخطوة التالية...) |
| 04 | 508 | المُجمِّع = صندوق البريد 08 | (الآن بعد أن تم تخزين قيم الإدخال في صندوقي البريد 08 و 09...) قم بتحميل القيمة الأولى مرة أخرى إلى الآلة الحاسبة (مع مسح كل ما كان موجوداً فيها). |
| 05 | 209 | المُجمِّع = المُجمِّع - صندوق البريد 09 | اطرح الرقم الثاني من القيمة الحالية للآلة الحاسبة (والتي تم ضبطها للتو على الرقم الأول) |
| 06 | 902 | صندوق الصادر = المُجمِّع | أخرج نتيجة الآلة الحاسبة إلى صندوق الإخراج. |
| 07 | ٠٠٠ | قف | أوقفوا مركز إدارة الأزمات |
استخدام الرموز التذكيرية والملصقات (لغة التجميع)
لغة التجميع هي لغة برمجة منخفضة المستوى تستخدم رموزًا مختصرة وعلامات بدلاً من رموز التعليمات الرقمية. على الرغم من أن وحدة التحكم المنطقية القابلة للبرمجة (LMC) تستخدم مجموعة محدودة من الرموز المختصرة، إلا أن سهولة استخدام رمز مختصر لكل تعليمة تتضح من لغة التجميع لنفس البرنامج الموضح أدناه - لم يعد المبرمج مضطرًا لحفظ مجموعة من الرموز الرقمية المجهولة، ويمكنه الآن البرمجة باستخدام مجموعة من الرموز المختصرة التي يسهل تذكرها. إذا كان الرمز المختصر تعليمة تتضمن عنوان ذاكرة ( سواء كانت تعليمة تفرع أو تحميل/حفظ بيانات )، فسيتم استخدام علامة لتسمية عنوان الذاكرة.
INP STA FIRST INP المحطة الثانية LDA أولاً جزء من الثانية خارج HLT الموعد الأول التاريخ الثاني
الملصقات
بدون استخدام التسميات، يُطلب من المبرمج حساب عناوين صناديق البريد ( الذاكرة ) يدويًا. في مثال الكود الرقمي ، إذا أُضيفت تعليمة جديدة قبل تعليمة HLT الأخيرة، فإن تعليمة HLT هذه ستنتقل من العنوان 07 إلى العنوان 08 (يبدأ ترقيم العناوين من العنوان 00). لنفترض أن المستخدم أدخل 600 كأول قيمة. ستعني التعليمة 308 تخزين هذه القيمة في العنوان 08 واستبدال تعليمة 000 (HLT). بما أن 600 تعني "الانتقال إلى عنوان صندوق البريد 00"، فإن البرنامج، بدلًا من أن يتوقف، سيعلق في حلقة لا نهائية.
للتغلب على هذه الصعوبة، تجمع معظم لغات التجميع ( بما في ذلك LMC ) بين الرموز المختصرة والتسميات . التسمية هي ببساطة كلمة تُستخدم إما لتسمية عنوان ذاكرة حيث يتم تخزين التعليمات أو البيانات، أو للإشارة إلى هذا العنوان في التعليمات.
عند تجميع البرنامج:
- يتم تحويل التسمية الموجودة على يسار رمز التعليمات إلى عنوان الذاكرة الذي تُخزَّن فيه التعليمات أو البيانات. على سبيل المثال: loopstart INP
- تأخذ التسمية الموجودة على يمين رمز التعليمات قيمة عنوان الذاكرة المشار إليه أعلاه. على سبيل المثال: BRA loopstart
- يُستخدم الوسم المُقترن بعبارة DAT كمتغير، حيث يُشير إلى عنوان الذاكرة الذي تُخزَّن فيه البيانات. على سبيل المثال، DAT 1 أو DAT رقم 1
في مثال لغة التجميع الذي يستخدم الرموز والتسميات، إذا تم إدراج تعليمة جديدة قبل تعليمة HLT الأخيرة، فسيكون موقع العنوان المسمى FIRST الآن في موقع الذاكرة 09 بدلاً من 08، وسيتم تحويل تعليمة STA FIRST إلى 309 (STA 09) بدلاً من 308 (STA 08) عند تجميع البرنامج.
لذلك تُستخدم الملصقات من أجل:
- تحديد تعليمة معينة كهدف لتعليمة BRANCH.
- يُحدد موقع الذاكرة كمتغير مُسمى (باستخدام DAT)، ويُمكن تحميل البيانات إلى البرنامج أثناء وقت التجميع لاستخدامها من قِبل البرنامج (لا يكون هذا الاستخدام واضحًا إلا عند التفكير في أنه لا توجد طريقة لإضافة 1 إلى عداد. يُمكن مطالبة المستخدم بإدخال 1 في البداية، ولكن من الأفضل تحميل هذه القيمة أثناء التجميع باستخدام DAT 1 واحد ).
مثال
سيقوم البرنامج أدناه بأخذ مدخلات المستخدم، ثم يقوم بالعد التنازلي حتى الصفر.
INP إخراج // تهيئة الإخراج LOOP BRZ QUIT // قم بتسمية عنوان الذاكرة هذا بـ LOOP. إذا كانت قيمة المُراكم تساوي 0، فانتقل إلى عنوان الذاكرة المُسمى LOOP. // يترك طرح واحد // اطرح القيمة المخزنة في العنوان واحد من المُراكم خارج حلقة BRA // انتقل (دون قيد أو شرط) إلى عنوان الذاكرة المسمى LOOP QUIT HLT // قم بتسمية عنوان الذاكرة هذا بـ QUIT ONE DAT 1 // قم بتخزين القيمة 1 في عنوان الذاكرة هذا، وقم بتسميته ONE (إعلان المتغير)
سيقوم البرنامج أدناه بأخذ مُدخل من المستخدم، وتربيعه، وإخراج الناتج، ثم تكرار العملية. إدخال الصفر سينهي البرنامج. ( ملاحظة: أي مُدخل ينتج عنه قيمة أكبر من 999 سيؤدي إلى سلوك غير مُحدد بسبب حدّ الأرقام المكونة من ثلاثة أرقام في وحدة التحكم المنطقية القابلة للبرمجة ).
ابدأ LDA صفرًا // تهيئة لتشغيل البرنامج عدة مرات نتيجة المحطة عدد الموظفين إدخال // مدخلات مقدمة من المستخدم BRZ END // انتقل إلى نهاية البرنامج إذا كانت قيمة الإدخال = 0 قيمة التخزين // تخزين المدخلات كقيمة حلقة LDA RESULT // تحميل النتيجة إضافة قيمة // أضف القيمة، وهي القيمة المُدخلة من قِبل المستخدم، إلى النتيجة نتيجة STA // تخزين النتيجة الجديدة عدّ LDA // تحميل العدّ أضف واحدًا // أضف واحدًا إلى العدد STA COUNT // تخزين العدد الجديد القيمة الفرعية // اطرح قيمة الإدخال التي أدخلها المستخدم من العدد BRZ ENDLOOP // إذا كانت القيمة صفرًا (تمت إضافة القيمة إلى النتيجة بمقدار القيمة عدة مرات)، فانتقل إلى ENDLOOP حلقة حمالة الصدر // انتقل إلى حلقة لمواصلة إضافة القيمة إلى النتيجة نهاية الحلقة LDA RESULT // تحميل النتيجة مخرجات // نتيجة الإخراج BRA START // انتقل إلى نقطة البداية لتهيئة البرنامج والحصول على قيمة إدخال أخرى END HLT // HALT - تم إدخال صفر، لذا انتهى الأمر! بيانات النتيجة // النتيجة المحسوبة (القيمة الافتراضية 0) COUNT DAT // عداد (القيمة الافتراضية 0) بيانات واحدة 1 // ثابت، قيمته 1 بيانات القيمة // المدخلات التي يقدمها المستخدم، القيمة المراد تربيعها (القيمة الافتراضية هي 0) بيانات الصفر // ثابت، قيمته 0 (القيمة الافتراضية 0)
ملاحظة: إذا لم تكن هناك بيانات بعد عبارة DAT، فسيتم تخزين القيمة الافتراضية 0 في عنوان الذاكرة.
In the example above, [BRZ ENDLOOP] depends on undefined behaviour, as COUNT-VALUE can be negative, after which the ACCUMULATOR value is undefined, resulting in BRZ either branching or not (ACCUMULATOR may be zero, or wrapped around). To make the code compatible with the specification, replace:
... LDA COUNT // Load the COUNT ADD ONE // Add ONE to the COUNT STA COUNT // Store the new COUNT SUB VALUE // Subtract the user provided input VALUE from COUNT BRZ ENDLOOP // If zero (VALUE has been added to RESULT by VALUE times), branch to ENDLOOP ...
with the following version, which evaluates VALUE-COUNT instead of COUNT-VALUE, making sure the accumulator never underflows:
... LDA COUNT // Load the COUNT ADD ONE // Add ONE to the COUNT STA COUNT // Store the new COUNT LDA VALUE // Load the VALUE SUB COUNT // Subtract COUNT from the user provided input VALUE BRZ ENDLOOP // If zero (VALUE has been added to RESULT by VALUE times), branch to ENDLOOP ...
Another example is a quine, printing its own machine code (printing source is impossible because letters cannot be output):
LOAD LDA 0 // Load position 0 into the accumulator. This line will be modified on each loop to load the next lines into the accumulator OUT // Output the accumulator's value. The accumulator's value will be the line that was just loaded SUB ONE // Subtract 1 from the value in the accumulator. This is so we can do the BRZ in the next step to see if we are on the last line in the program BRZ ONE // If the previous subtraction has made the accumulator 0 (which means we had the value 001 in the accumulator), then branch to position ONE LDA LOAD // Load the LOAD position into the accumulator, this is in preparation to increment the address digits for this position ADD ONE // Increment the position digits for the LOAD line. The value currently in the accumulator would, if read as an instruction, load the next line into the accumulator, compared to the last line loaded STA LOAD // Store the newly incremented LOAD line back in the LOAD position BRA LOAD // Return to the beginning of the loop ONE DAT 1 // The variable ONE. If read as an instruction, this will be interpreted as HLT/COB and will end the program
This quine works using self-modifying code. Position 0 is incremented by one in each iteration, outputting that line's code, until the code it is outputting is 1, at which point it branches to the ONE position. The value at the ONE position has 0 as opcode, so it is interpreted as a HALT/COB instruction.
See also
- CARDboard Illustrative Aid to Computation, another instructional model
- TIS-100 (video game)
- Hack computer, another educational abstract computer
- Human Resource Machine, a computer game heavily influenced by the LMC
- WDR paper computer
- Digi-Comp I
- The Little Man Stack Machine, an expansion on the LMC with dedicated stack instructions.
- محاكي LMC عبر الإنترنت من تصميم بيتر هيغينسون .
- Tiny Binary Computer ، وهو محاكاة حاسوب ثنائي تستخدم امتدادًا لمجموعة تعليمات LMC.
مراجع
- ↑ "الحاسوب الصغير" . جامعة ولاية إلينوي . 1 مايو 2000. مؤرشف من الأصل في 27 فبراير 2009. تم الاطلاع عليه في 8 مارس 2009 .
- ↑ يورسيك، و.؛ أوزبورن، هـ. (2001). "مجموعة من الحواسيب الصغيرة: أدوات تعليمية لمحاكاة الحاسوب المرئية". وقائع مؤتمر محاكاة الشتاء لعام 2001 (رقم التصنيف 01CH37304) . المجلد 2. ص 1632. doi : 10.1109/WSC.2001.977496 . ISBN 0-7803-7307-3. S2CID 18907923 .
- ↑ يورسيك، و.؛ برومباو، ل. (2001). "محاكاة حاسوبية لرجل صغير عبر الإنترنت". وقائع الندوة الفنية الثانية والثلاثين لجمعية SIGCSE حول تعليم علوم الحاسوب - SIGCSE '01 . ص 204. doi : 10.1145/364447.364585 . ISBN 1581133294. S2CID 14794750 .
- ↑ أوزبورن، هـ.؛ يورسيك، و. (2002). "النطاق التعليمي للمحاكاة المرئية لنموذج بنية حاسوب الرجل الصغير". المؤتمر السنوي الثاني والثلاثون لآفاق التعليم . الصفحات من S4G إلى S19. doi : 10.1109/FIE.2002.1158742 . ISBN 0-7803-7444-4. S2CID 10324295 .
لغة سي++
- تضمين <iostream>
باستخدام مساحة الاسم std؛ int mainO [ {
طول وعرض ومساحة الطفو؛
روابط خارجية
- ريتشارد ج. بوفينيللي: التدريس: مقدمة في مكونات الحاسوب المادية والبرمجية: حاسوب الرجل الصغير
- حاسوب "الرجل الصغير"
أجهزة المحاكاة
متصل
- آلات تعليمية تجريدية
- مقدمات متعلقة بالحاسوب في عام 1965
