Программирование с основ: Pep/8

Вступление

Кому интересно как работает процессор? В наше время любой желающий может купить книжку для дураков, скачать Visual Studio и начать писать программы на VB. Через 21 день он научится бросать контролы на форму и писать простейшие обработчики событий. Программирование сведется к копированию подходящих примеров кода из Гугля, и останется черным ящиком, устройство которого будет абсолютно непонятно.

А что, если попробовать сначала, с основ? Понять как и почему работает процессор, равнозначно понять программирование в принципе. Потому что все остальное это абстракция призванная упростить работу. Но любую абстракцию можно использовать лишь хорошо понимая, что остается за пределами. Если вам интересно, то приглашаю прочитать цикл статей об основах программирования.

Итак, что такое процессор? Это конвейер по обработке данных. Концептуально процессор выполняет следующие 5 шагов:

  1. Fetch -> выборка команды
  2. Decode -> декодирование команды
  3. Increment -> увеличение счетчика
  4. Execute -> выполнение команды
  5. Repeat -> повтор цикла


Что такое команда? Это набор байтов которые знает процессор. У каждого семейства процессоров свои команды, и большинство из них предназначены для манипулирования данными. Что такое данные? Это те же байты, но которые логически представляют собой информацию. Данные и команды физически расположены в одном пространстве и у каждого байта есть свой адрес. В чем же различие между данными и командами? Ни в чем, только в их предназначении: команды предназначены для выполнения операций на данными. Поскольку физического различия нет, в нашей воле заставить процессор «исполнять данные» и «манипулировать коммандами», т.е. можно писать программы которые интерпретируют другие программы как данные. Кстати описанная архитектура, была придумана Джоном фон Нейманом и является самой распостраненной архитектурой в современном мире.

Поскольку у каждого процессора свои команды, а процессоров много, имеет смысл выбрать какой нибудь простой процессор, на котором можно изучить принципы программирования, которые потом помогут справиться с реальными машинами. Для этой цели я выбрал Pep/8. Это 16-битный CISC процессор, который был создан специально для студентов. У этого процессора 39 команд и 8 режимов адресации.

В железе он не существует, но его ассемблер и эмулятор можно скачать отсюда.

Окно эмулятора выглядит примерно вот так:

Слева у нас есть таблички для исходного кода на ассемблере, транслированного кода и ассемблерного листинга. Посередине перечислены регистры и флаги процессора, а так же терминал для входных/выходных данных. Справа дамп памяти.



Список команд можно посмотреть в меню Help-Pep/8 Reference.

Начнем пожалуй, как положено с Hello World!.. Вот транслированный код, который нужно скопировать в поле Object Code, потом выбрать Build-Load, и Build-Execute:

50 00 48 50 00 65 50 00 6C 50 00 6C 50 00 6F 50 00 20 50 00 57 50 00 6F 50 00 72 50 00 6C 50 00 64 50 00 21 00 zz


Если загрузка в память не удается проверьте что у вас не лишних пробелов и переводов строк. Эмулятор очень разборчив к коду. В результате у вас должна появиться строка «Hello World!» в окне Output. А в окне Assembler Listing можно лицезреть красивую табличку:



Слева направо: Адрес первого байта команды, обьектный код, метка (их нет), мнемоника, операнд, комментарий. Итак в Pep/8 команды бывают 3-байтные или однобайтные. Выполнение начинается по адресу 0000 и продолжается до тех пор пока не встретится байт 00 (STOP). Так первая команда лежит по адресу 0000, вторая по адресу 0003 и т.д. Счет идет в шестнадцатиричной системе счисления. Меткий глаз заметит что все команды одинаковы за исключением последнего байта и будет прав. Команда CHARO выводит ровно один символ на экран. Какой символ? Режим адресации указан immediate (i), а значит команда CHARO выведен на экран тот байт что указан в операнде. В следующем примере например я использую режим direct (d), в котором команда CHARO выведет на экран содержимое памяти по адресу указанному в операнде:



Команда .BYTE не является командой процессора, она всего лишь указывает ассемблеру что нужно зарезервировать байт в памяти. Здесь буквы лежат в памяти начиная с адреса 0025. Соответственно операнды команд CHARO указывают на эти адреса. Что будет если поменять у первой команды d, обратно на i? Тогда CHARO интерпретирует байт 25 не как адрес в памяти, а как непосредственный символ и напечатает на экране %, согласно таблице ASCII. Можно ли оптимизировать эту программу? Во первых можно воспользоваться командой STRO:



Команда STRO будет выводит на экран все символы с указанного символа до тех пор пока не встретит символ 00. .ASCII так же как и .BYTE не является командой процессора, а всего лишь указывает ассемблеру зарезервировать блок в памяти с указаным содержимым.

Вступительную статью завершу вопросом для внимательных. Какой будет результат следующего кода:



За сим откланяюсь, благодарю за внимание.


0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.