Маленький компьютер человека - Little man computer

В Маленький Человек Компьютер (LMC) является учебным модель из компьютер, созданный Dr. Стюарт Мэдник в 1965 г.[1] LMC обычно используется для обучения студентов, потому что он моделирует простой фон Неймана архитектура компьютер, обладающий всеми основными функциями современного компьютера. Он может быть запрограммирован в машинном коде (хотя и в десятичном, а не в двоичном) или ассемблерном коде.[2][3][4]

Модель LMC основана на концепции маленького человека, запертого в закрытой почтовой комнате (аналог компьютера в этом сценарии). В одном конце комнаты 100 почтовых ящиков (объем памяти ), пронумерованные от 0 до 99, каждая из которых может содержать 3-значную инструкцию или данные (в диапазоне от 000 до 999). Кроме того, на другом конце есть два почтовых ящика с надписью INBOX и ИСХОДЯЩИЕ которые используются для приема и вывода данных. В центре комнаты находится рабочая зона, содержащая простой калькулятор с двумя функциями (сложение и вычитание), известный как Аккумулятор и сбрасываемый счетчик, известный как Программный счетчик. Счетчик программ содержит адрес следующей инструкции, которую будет выполнять Маленький Человек. Этот Программный Счетчик обычно увеличивается на 1 после выполнения каждой инструкции, что позволяет Маленькому Человеку работать с программой последовательно. Ответвляться инструкции позволяют выполнять итерацию (циклы) и условный структуры программирования, которые необходимо включить в программу. Последнее достигается путем установки Программного Счетчика на непоследовательный адрес памяти, если выполняется определенное условие (обычно значение, хранящееся в аккумуляторе, равно нулю или положительно).

Как указано в фон Неймана архитектура, каждый почтовый ящик (обозначающий уникальную ячейку памяти) содержит как инструкции, так и данные. Поэтому необходимо следить за тем, чтобы программный счетчик не достиг адреса памяти, содержащей данные, - иначе Маленький Человек попытается обработать это как инструкцию. Этим можно воспользоваться, написав инструкции в почтовые ящики, которые должны интерпретироваться как код, для создания самомодифицирующегося кода. Чтобы использовать ЛКМ, пользователь загружает данные в почтовые ящики, а затем сигнализирует Маленькому Человеку начать выполнение, начиная с инструкции, хранящейся по нулевому адресу памяти. Сброс счетчика программы на ноль эффективно перезапускает программу, хотя и в потенциально другом состоянии.

Цикл исполнения

Чтобы выполнить программу, человечек выполняет следующие действия:

  1. Проверьте счетчик программ на номер почтового ящика, который содержит инструкцию программы (т. Е. Ноль в начале программы)
  2. Получите инструкцию из почтового ящика с этим номером. Каждая инструкция содержит два поля: код операции (указывающий на выполняемую операцию) и поле адреса (указывающее, где найти данные для выполнения операции).
  3. Увеличьте счетчик программы (чтобы он содержал номер почтового ящика следующей инструкции)
  4. Расшифруйте инструкцию. Если инструкция использует данные, хранящиеся в другом почтовом ящике, используйте поле адреса, чтобы найти номер почтового ящика для данных, с которыми он будет работать, например 'получить данные из почтового ящика 42')
  5. Получите данные (из входа, аккумулятора или почтового ящика с адресом, определенным на шаге 4)
  6. Выполнить инструкцию на основе заданного кода операции
  7. Разветвите или сохраните результат (в выводе, накопителе или почтовом ящике с адресом, определенным на шаге 4)
  8. Вернитесь к счетчику программ, чтобы повторить цикл или остановить

Команды

Хотя LMC действительно отражает фактическую работу двоичный процессоров, простота десятичный числа были выбраны, чтобы минимизировать сложность для студентов, которым может быть неудобно работать в двоичном /шестнадцатеричный.

инструкции

Некоторые симуляторы LMC программируются напрямую с использованием 3-значных числовых инструкций, а некоторые используют трехбуквенные мнемонические коды и метки. В любом случае набор инструкций намеренно очень ограничен (обычно около десяти инструкций), чтобы упростить понимание. Если LMC использует мнемонические коды и метки, то они преобразуются в 3-значные числовые инструкции при сборке программы.

В таблице ниже показан типичный набор числовых команд и эквивалентные мнемонические коды.

инструкции
Числовой кодМнемонический кодИнструкцияОписание
1xxДОБАВИТЬДОБАВИТЬДобавьте значение, хранящееся в почтовом ящике xx, к любому значению, которое в настоящее время находится в аккумуляторе (калькуляторе).
Примечание: содержимое почтового ящика не изменяется, и действия аккумулятора (калькулятора) не определены для инструкций добавления, которые приводят к суммам, превышающим 3 цифры. Аналогично SUBTRACT, можно установить отрицательный флаг при переполнении.
2xxSUBВЫЧИТАТЬВычтите значение, хранящееся в почтовом ящике xx, из любого значения, которое в настоящее время находится в аккумуляторе (калькуляторе).
Примечание: содержимое почтового ящика не изменяется, и действия аккумулятора не определены для инструкций вычитания, которые приводят к отрицательным результатам - однако будет установлен отрицательный флаг, чтобы 7xx (BRZ) и 8xx (BRP) можно использовать правильно.
3xxSTAХРАНИТЬХранить содержимое аккумулятора в почтовом ящике xx (деструктивно).
Примечание: содержимое аккумулятора (калькулятора) не изменяется (неразрушающий), но содержимое почтового ящика заменяется независимо от того, что там было (разрушающее)
5xxLDAНАГРУЗКАЗагрузите значение из почтового ящика xx (неразрушающее) и введите его в аккумулятор (разрушающее).
6xxБЮСТГАЛЬТЕРОТВЕТВЛЯТЬСЯ (безусловный)Установите программный счетчик на заданный адрес (значение xx). То есть значение xx будет следующей выполненной инструкцией.
7xxBRZФИЛИАЛ, ЕСЛИ НУЛЬ (условный )Если аккумулятор (калькулятор) содержит значение 000, установите программный счетчик на значение xx. В противном случае ничего не делайте. Учитывается ли отрицательный флаг, не определено. Когда СУБТРАКТ опустошает аккумулятор, этот флаг устанавливается, после чего аккумулятор не определен, потенциально равен нулю, в результате чего поведение BRZ не определено при недополнении. Предлагаемое поведение - ветвление, если аккумулятор равен нулю и отрицательный флаг не установлен.
Примечание: поскольку программа хранится в памяти, данные и инструкции программы имеют одинаковый формат адреса / расположения.
8xxBRPФИЛИАЛ, ЕСЛИ ПОЛОЖИТЕЛЬНО (условно)Если аккумулятор (калькулятор) равен 0 или положителен, установите программный счетчик на значение xx. В противном случае ничего не делайте. Поскольку ячейки памяти LMC могут содержать только значения от 0 до 999, эта инструкция зависит исключительно от отрицательного флага, установленного при недостаточном значении для SUBTRACT и, возможно, от переполнения при ADD (undefined).
Примечание: поскольку программа хранится в памяти, данные и инструкции программы имеют одинаковый формат адреса / расположения.
901INPВХОДЗайдите во INBOX, получите значение от пользователя и поместите его в аккумулятор (калькулятор)
Примечание: это перезапишет любое значение, которое было в аккумуляторе (деструктивно)
902ИЗВЫХОДСкопируйте значение из аккумулятора (калькулятора) в OUTBOX.
Примечание: содержимое аккумулятора не изменяется (неразрушающий).
000HLT / COBHALT / COFFEE BREAKПрекратить работу / завершить программу.
DATДАННЫЕЭто ассемблер инструкция, которая просто загружает значение в следующий доступный почтовый ящик. DAT также можно использовать вместе с метками для объявления переменных. Например, DAT 984 сохранит значение 984 в почтовом ящике по адресу инструкции DAT.

Примеры

Использование цифровых кодов инструкций

Эта программа (инструкция 901 к инструкции 000) записывается с использованием числовых кодов. Программа принимает на вход два числа и выводит разницу. Обратите внимание, что выполнение начинается в почтовом ящике 00 и заканчивается в почтовом ящике 07. Недостатки программирования LMC с использованием числовых кодов команд обсуждаются ниже.

Почтовый ящикЧисловой кодОперацияКомментарии
00901ВХОДНОЙ ЯЩИК -> АККУМУЛЯТОРВВЕДИТЕ первое число, введите в калькулятор (стирая все, что там было)
01308АККУМУЛЯТОР -> ПАМЯТЬ [08]СОХРАНИТЕ текущее значение калькулятора (чтобы подготовиться к следующему шагу ...)
02901ВХОДНОЙ ЯЩИК -> АККУМУЛЯТОРВВЕДИТЕ второе число, введите в калькулятор (стирая все, что там было)
03309АККУМУЛЯТОР -> ПАМЯТЬ [09]СОХРАНИТЕ текущее значение калькулятора (опять же, чтобы подготовиться к следующему шагу ...)
04508ПАМЯТЬ [08] -> АККУМУЛЯТОР(Теперь, когда оба значения INPUT хранятся в почтовых ящиках 08 и 09 ...)

ЗАГРУЗИТЕ первое значение обратно в калькулятор (удалив все, что там было)

05209АККУМУЛЯТОР = АККУМУЛЯТОР - ПАМЯТЬ [09]ВЫЧИТАЙТЕ второе число из текущего значения калькулятора (которое было только что установлено на первое число)
06902АККУМУЛЯТОР -> ВЫХОДНОЙ ЯЩИКВЫВОДИТЕ результат калькулятора в OUTBOX
07000(операция не выполняется)ОСТАНОВИТЬ БМО

Использование мнемоники и меток

язык ассемблера - это язык программирования низкого уровня, который использует мнемонику и метки вместо числовых кодов инструкций. Хотя LMC использует только ограниченный набор мнемоник, удобство использования мнемонический поскольку каждая инструкция становится очевидной из языка ассемблера той же программы, показанной ниже - программисту больше не требуется запоминать набор анонимных числовых кодов и теперь он может программировать с набором более запоминающихся мнемонических кодов. Если мнемоника - это инструкция, которая включает адрес памяти (либо инструкция перехода, либо загрузка / сохранение данных), то для имени адреса памяти используется метка.

Этот пример программы можно скомпилировать и запустить на симуляторе LMC.[5] доступно на сайте Йоркский университет (Торонто, Онтарио, Канада) или в настольном приложении, написанном Майком Коли.[6] Все эти симуляторы включают полные инструкции и примеры программ, ассемблер для преобразования кода сборки в машинный код, управляющие интерфейсы для выполнения и мониторинга программ, а также пошаговое подробное описание каждой инструкции LMC.
INPSTA FIRSTINPSTA SECONDLDA FIRSTSUB SECONDOUTHLTFIRST DATSECOND DAT

Этикетки

Без меток программист должен вручную рассчитать почтовый ящик (объем памяти) адреса. в пример числового кода, если новая инструкция должна быть вставлена ​​перед последней инструкцией HLT, то эта инструкция HLT переместится с адреса 07 на адрес 08 (маркировка адреса начинается с адреса 00). Предположим, пользователь ввел 600 в качестве первого ввода. Команда 308 будет означать, что это значение будет сохранено в ячейке адреса 08 и перезапишет команду 000 (HLT). Поскольку 600 означает «переход к адресу почтового ящика 00», программа вместо остановки могла бы застрять в бесконечном цикле.

Чтобы обойти эту трудность, большинство языков ассемблера (включая БМО) объедините мнемонику с этикетки. Метка - это просто слово, которое используется либо для обозначения адреса памяти, где хранятся инструкция или данные, либо для ссылки на этот адрес в инструкции.

Когда программа собрана:

  • Метка слева от мнемоники инструкции преобразуется в адрес памяти, в котором хранятся инструкция или данные. т.е. loopstart INP
  • Метка справа от мнемоники команды принимает значение адреса памяти, упомянутого выше. т.е. BRA loopstart
  • Метка в сочетании с оператором DAT работает как переменная, она маркирует адрес памяти, в котором хранятся данные. т.е. один DAT 1 или же number1 DAT

в язык ассемблера пример который использует мнемонику и метки, если новая инструкция была вставлена ​​перед последней инструкцией HLT, тогда адрес, помеченный FIRST, теперь будет в ячейке памяти 09, а не 08, и инструкция STA FIRST будет преобразована в 309 (STA 09), а не 308 (STA 08) при сборке программы.

Поэтому ярлыки используются для:

  • идентифицировать конкретную инструкцию как цель для инструкции BRANCH.
  • идентифицировать ячейку памяти как именованную переменную (используя DAT) и при необходимости загружать данные в программу во время сборки для использования программой (это использование неочевидно до тех пор, пока не будет принято во внимание, что нет способа добавить 1 к счетчику. попросите пользователя ввести 1 в начале, но было бы лучше, чтобы это было загружено во время сборки, используя один DAT 1)

Пример

Программа ниже примет пользовательский ввод и обратный отсчет до нуля.

     INP OUT // Инициализировать выход LOOP BRZ QUIT // Обозначьте этот адрес памяти как LOOP. Если значение аккумулятора равно 0, перейдите к адресу памяти, помеченному QUIT SUB ONE // Вычтите значение, хранящееся по адресу ONE, из аккумулятора OUT BRA LOOP // Перейдите (безусловно) к адресу памяти, помеченному LOOPQUIT HLT // Обозначьте этот адрес памяти as QUITONE DAT 1 // Сохраняем значение 1 в этом адресе памяти и помечаем его ОДИН (объявление переменной)

Программа ниже примет пользовательский ввод, возведет его в квадрат, выведет ответ и затем повторится. Ввод нуля завершит программу.
(Примечание: вход, который приводит к значению больше 999, будет иметь неопределенное поведение из-за ограничения 3-значного числа LMC.).

START LDA ZERO // Инициализация для выполнения нескольких программ STA RESULT STA COUNT INP // Пользовательский ввод BRZ END // Переход к END, если input = 0 STA VALUE // Сохранение ввода как VALUELOOP LDA RESULT // Загрузить РЕЗУЛЬТАТ ДОБАВИТЬ ЗНАЧЕНИЕ / / Добавить VALUE, введенное пользователем, в RESULT STA RESULT // Сохранение нового RESULT LDA COUNT // Загрузить COUNT ADD ONE // Добавить ЕДИНИЦУ в COUNT STA COUNT // Сохранить новое COUNT SUB VALUE // Вычесть пользователя предоставленный вход VALUE from COUNT BRZ ENDLOOP // Если ноль (VALUE было добавлено к RESULT в VALUE раз), перейти к ENDLOOP BRA LOOP // Перейти к LOOP, чтобы продолжить добавление VALUE к RESULTENDLOOP LDA RESULT // Загрузить RESULT OUT // Выходной результат BRA START // Переход к START для инициализации и получение другого входа VALUEEND HLT // HALT - был введен ноль, готово! RESULT DAT // C вычисляемый результат (по умолчанию 0) COUNT DAT // Счетчик (по умолчанию 0) ONE DAT 1 // Константа, значение 1VALUE DAT // Ввод, предоставленный пользователем, значение, которое нужно возвести в квадрат (по умолчанию 0) ZERO DAT // Константа, значение 0 (по умолчанию 0)

Примечание. Если после оператора DAT нет данных, то в адресе памяти сохраняется значение по умолчанию 0.

В приведенном выше примере [BRZ ENDLOOP] зависит от неопределенного поведения, так как COUNT-VALUE может быть отрицательным, после чего значение ACCUMULATOR не определено, в результате BRZ либо ветвится, либо нет (ACCUMULATOR может быть равен нулю или закругляться). Чтобы код был совместим со спецификацией, замените:

        ... LDA COUNT // Загрузить COUNT ADD ONE // Добавить ЕДИНИЦУ в COUNT STA COUNT // Сохранить новое COUNT SUB VALUE // Вычесть введенное пользователем значение VALUE из COUNT BRZ ENDLOOP // Если ноль (VALUE было добавлено в РЕЗУЛЬТАТ в VALUE раз), перейти к ENDLOOP ...

со следующей версией, которая оценивает VALUE-COUNT вместо COUNT-VALUE, чтобы аккумулятор никогда не переполнялся:

        ... LDA COUNT // Загрузить COUNT ADD ONE // Добавить ЕДИНИЦУ в COUNT STA COUNT // Сохранить новое COUNT LDA VALUE // Загрузить VALUE SUB COUNT // Вычесть COUNT из введенного пользователем значения VALUE BRZ ENDLOOP // Если ноль (VALUE было добавлено к RESULT VALUE раз), перейти к ENDLOOP ...

Другой пример - лоза, печать собственного машинного кода (источник печати невозможен, потому что буквы не выводятся):

LOAD LDA 0 // Загрузить позицию 0 в аккумулятор. Эта строка будет изменяться в каждом цикле для загрузки следующих строк в аккумулятор OUT // Вывод значения аккумулятора. Значение аккумулятора будет только что загруженной строкой SUB ONE // Вычтите 1 из значения в аккумуляторе. Это сделано для того, чтобы мы могли выполнить BRZ на следующем шаге, чтобы увидеть, находимся ли мы на последней строке в программе BRZ ONE // Если предыдущее вычитание сделало аккумулятор 0 (что означает, что у нас было значение 001 в аккумуляторе), затем перейти к позиции ONE LDA LOAD // Загрузить позицию LOAD в аккумулятор, это подготовка к увеличению цифр адреса для этой позиции ADD ONE // Увеличиваем цифры позиции для строки LOAD. Текущее значение в аккумуляторе при чтении в виде инструкции загрузит в аккумулятор следующую строку по сравнению с последней загруженной строкой STA LOAD // Сохраните вновь увеличенную строку LOAD обратно в позицию LOAD BRA LOAD // Вернитесь к начало циклаONE DAT 1 // Переменная ONE. Если читать как инструкцию, это будет интерпретировано как HLT / COB и завершит программу.

Этот quine работает с использованием самомодифицирующийся код. Позиция 0 увеличивается на единицу в каждой итерации, выводя код этой строки, пока код, который она выводит, не станет 1, после чего она переходит в ОДНУ позицию. Значение в позиции ONE имеет код операции 0, поэтому он интерпретируется как инструкция HALT / COB.

Смотрите также

Рекомендации

  1. ^ "Маленький компьютер". Государственный университет Иллинойса. 1 мая 2000 г. Архивировано с оригинал 27 февраля 2009 г.. Получено 8 марта, 2009.
  2. ^ Юрчик, З .; Осборн, Х. (2001). «Толпа компьютеров Little Man: обучающие инструменты на визуальном компьютерном симуляторе». Труды Зимней конференции по моделированию 2001 г. (Кат. № 01CH37304). 2. п. 1632. Дои:10.1109 / WSC.2001.977496. ISBN  0-7803-7307-3.
  3. ^ Юрчик, З .; Брамбо, Л. (2001). "Интернет-симулятор маленького человечка". Материалы тридцать второго технического симпозиума SIGCSE по образованию в области компьютерных наук - SIGCSE '01. п. 204. Дои:10.1145/364447.364585. ISBN  1581133294.
  4. ^ Osborne, H .; Юрчик, В. (2002). «Образовательный диапазон визуальных симуляций парадигмы компьютерной архитектуры маленького человека». 32-я ежегодная конференция «Границы образования». стр. S4G – S19. Дои:10.1109 / FIE.2002.1158742. ISBN  0-7803-7444-4.
  5. ^ Чен, Стивен Ю.; Кадмор, Уильям С. "Маленький компьютер". Йоркский университет. Получено 7 октября, 2010.
  6. ^ Коли, Майк. "Маленький компьютер". Получено 12 апреля, 2012.

внешняя ссылка

Симуляторы

В сети

Другой