Программирование в машинном коде

Рассмотрим несколько примеров простейших МиК-программ, иллюстрирующих некоторые принципиальные моменты техники программирования в машинных языках вообще.

Задача 1. Написать МиК-программу  нахождения разности двух заданных целых чисел.

Решение. Алгоритм решения данной задачи, составленный с учётом системы команд МиК, мог бы представлять  собой следующую последовательность шагов:

Шаг_1. Ввести уменьшаемое (in);

Шаг_2. Сохранить введённое данное в ячейке ОП  (st);

Шаг_3. Ввести вычитаемое  (in);

Шаг_4. Сохранить введённое данное в ячейке ОП  (st);

Шаг_5. Загрузить в сумматор сохранённое в ОП уменьшаемое (ld);

Шаг_6. Найти разность (sub);

Шаг_7. Вывести разность (out);

Шаг_8. Остановиться (halt).

Попытка перевода этого алгоритма в МиК-программу немедленно ставит вопрос о распределении памяти. Действительно, мы должны  решить:

1) В какой ячейке оперативной памяти сохранить введённое уменьшаемое;

2) В какой ячейке оперативной памяти сохранить введённое вычитаемое;

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

При этом заметим, что нет нужды заботиться о месте сохранения получаемого результата (разности), т.к. получив результат на сумматоре, мы имеем возможность сразу же, минуя ОП, вывести его на экран дисплея.

Поскольку у нас имеется большая свобода в вариантах ответов на заданные выше вопросы, то,  действуя  почти произвольно, остановимся на таком варианте:

 Распределение памяти МиК для решения задачи 1:

Адрес сохранения уменьшаемого

Адрес сохранения вычитаемого

Адрес загрузки программы

       0400

      0402

        0404

Всё же,  существующие в нашем выборе ограничения, которые объясняют употребление нами словосочетания “почти прозвольно”,   сводятся к следующему.

Во-первых, мы должны оставаться в рамках диапазона, составляющего полное адресное пространство  ОП машины  МиК ( 0000 – 9999 );

Во-вторых, нам следует помнить, что каждое числовое данное занимает не один, а два байта. Поэтому, нельзя было бы, например, уменьшаемое и вычитаемое расположить, соответственно, по адресам 0400 и 0401.

В-третьих, необходимо учесть, что команды программы, начинаясь с адреса её загрузки, записываются строго последовательно, без пропусков занимая непрерывный блок памяти. Поэтому, нужно следить за тем, чтобы блок этот не разрывался ячейками, отводимыми под данные. Так, выбор для уменьшаемого слова с адресом 0410 был бы в этом смысле ошибочен (подумайте, к чему привела бы такая ошибка!);

И, наконец, удобней располагать данные в памяти перед программным кодом, а не после него (почему?).

 Теперь мы готовы привести полную запись МиК-программы решения поставленной задачи:

Адреса Данные Комментарии
0400 ? место уменьшаемого
0402 ? место вычитаемого
0404 01   in (ввод)
0405 22 0400                                       st (запись в память)
0408 01   in (ввод)
0409 22 0402                                       st (запись в память)
0412 21 0400                                       ld (загрузка из памяти)
0415 11 0402                                       sub (вычитание)
0418 02 0ut (вывод)
0419 99 halt (остановка)

 Заметим, что в памяти, в отличие от нашей, “очеловеченной” формы записи, программа никак не структурирована и (начиная с адреса загрузки - 0404)  “выглядит” следующим образом:  01220400012204022104001104020299.

Но если в  РА поместить начальный её адрес 0404 и запустить процессор, то, в соответствии с аппаратным алгоритмом выполнения команд, он последовательно распознает и выполнит все составляющие эту программу команды. Не поленитесь, и мысленно промоделируйте эти действия процессора.

Задача 2. Написать МиК-программу, выбирающую наибольшее из двух заданных чисел.

Решение. Обозначим первое из заданных чисел через m, а второе – через n. Тогда для достижения поставленной цели,  мы можем воспользоваться следующим алгоритмом:

Шаг_1. Ввести значение m (in);

Шаг_2. Сохранить введённое значение m в ячейке ОП  (st);

Шаг_3. Ввести значение n (in);

Шаг_4. Сравнить n  и  m, вычислив их разность n- (cmp);

Шаг_5. Если вычисленная на предыдущем шаге разность отрицательна,   перейти на Шаг_ 7  (jm);

Шаг_6. Перейти на Шаг_8 (jmp);

Шаг_7. Взять в качестве результата значение m (ld).

Шаг_8. Вывести результат (out);

Шаг_9. Остановиться (halt). 

 В отличие от предыдущего линейного алгоритма, шаги и команды соответствующей программы которого выполнялись  в естественном порядке  (т.е. в порядке их записи), данный алгоритм, как мы видим, содержит разветвления, а потому является нелинейным. Реализация этой нелинейности в программе будет достигаться за счёт использования команд перехода. Как и при решении предыдущей задачи, распределим память: 

Распределение памяти МиК для решения задачи 2 

Адрес сохранения значения m

Адрес загрузки программы

       0300

        0302

 Попытавшись записать МиК-программу, мы обнаружим, что появилась дополнительная трудность: адресные части команд перехода (jm, jmp) не удаётся записать сразу. Они могут быть конкретизированы только после того, как в программе определятся адреса  команд, на которые ссылаются эти команды перехода. Поэтому, возможно, программа сначала будет записана c неопределёнными адресными частями указанных команд  в виде:

Адреса

Данные и команды

Комментарии

0300

?

Резервировано для значения  m

0302

01

In {Шаг_1} Ввод m

0303

22  0300

St {Шаг_2} Cохранение m в ОП.

0306

01

In {Шаг_3} Ввод n;  сохранять n  в ОП не надо!

0307

12  0300

Cmp {Шаг_4} Формирование ПР по разности n-m

0310

34  . . .

Jm {Шаг_5}  Переход, если ПР<0

0313

30  . . .

Jmp {Шаг_6} Безусловный переход (при ПР>=0)

0316

21 0300

Ld {Шаг_7} Загрузка в сумматор числа m

0319

02

Out {Шаг_8} Вывод результата

0320

99

Halt {Шаг_9} Остановка

Теперь определилась информация для  записи адресных частей команд с адресами 0310 и 0313, что позволяет представить программу решения данной задачи в окончательной форме:

Адреса

Данные и команды

Комментарии

0300

?

Резервировано для значения  m

0302

01

In {Шаг_1}

0303

22  0300

St {Шаг_2}

0306

01

In {Шаг_3}

0307

12  0300

Cmp {Шаг_4} Формирование ПР

0310

34  0316

Jm {Шаг_5}  Переход, если ПР<0

0313

30  0319

Jmp {Шаг_6} Безусловный переход (при ПР>=0)

0316

21  0300

Ld {Шаг_7} Загрузка m

0319

02

Out {Шаг_8} Вывод результата

0320

99

Halt {Шаг_9} Остановка

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

Программный эмулятор машины МiK, руководство, справочник и пошаговая инструкция по его использованию показаны ниже и доступны для скачивания ЗАРЕГИСТРИРОВАННЫМ  пользователям.

4.76923
Your rating: Нет Average: 4.8 (13 votes)

Комментарии

МиК

Сложновато так с первого раза, попробую еще раз справочник изучить

МиК

программа мне понравилась, интересна, почти поняла как работать

У тебя при вводе команд

У тебя при вводе команд ошибки не выбивает?

мик

бывает

Александр, Валерия, МиК, ...

Александр, Валерия, МиК. Молодцы что пробуете. Не рассчитываю, что всё сразу поймёте, но важно начать, на практике многое прояснится.
А сейчас с нетерпением жду предметных вопросов по МиК (от всех, конечно).

Александр, любые контрольные мероприятия будут заявляться хотя бы за сутки, не беспокойтесь.

Фотографии-аватары на сайте (во всяком случае, их большинство), наконец, стали обретать и смысл и качество. Спасибо! Я чувствую себя в аудитории и вижу ваши глаза. А это значит - говорю не в пустоту.
Маргарита, эта фотка неплоха, уточните только, кто из двоих на ней - ВЫ :)) Но честно говоря, та, мелькнувшая второй Ваша фотка была наилучшей.
Рустэм, чего уж спрашивать, конечно же супер!

За все ваши комплименты и благодарности - ответное СПАСИБО, но (ещё раз!)
жду ваших предметных вопросов!

Пока сложновато с первого

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

сложновато пока , буду

сложновато пока , буду пытаться еще

При вводе любой команды, у

При вводе любой команды, у меня почему-то "выскакивает" ошибка, может я что-то не так делаю?

Александр и остальные, МиК...

Давайте практическую работу с интерпретатором МиК оставим на лабораторки.
Сейчас важнее разобраться в командах МиК и в том, как составлять простейшие программки пока на бумаге ...

Есть над чем поразмыслить

Смысл задачь понятен, немного затрудняюсь в правельной записи алгоритма. А именно из-за того что привык работать, как вы сказали "блоками" тут же нужна более детальная запись: 22 0300 St {Шаг_2} Cохранение m в ОП. (поправте меня если я ошибаюсь) 22- "это команда сохранения в ОП", а 0300- это ячейка "m". Если это так, то у меня возникает вопрос: 01- это команда ввода переменных "m" и "n", почему их нельзя объединить в один шаг? И на основании этого вопроса возникает другой, (шаг 5 и 6) что означает "безусловный переход"?? и можно ли опять же объединить эти действия путем одного вывода строчки "ПР<0 в противном случае ПР>=0" и конечный вывод результата уже под командой 02. Я понимаю что МиК устроен так и это целостная программа, но чисто теоритически на бумаге, можно скомпоновать алгорит и тем самым его немного упростить?.
Что касается самой программы, то за нее спасибо. Вопросы конечно есть, но как уже писали ребята их можно решить толкько прямой практикой, сразу что-то понять трудновато будет.
Зарания спасибо.

Есть над чем поразмыслить

Смысл задачь понятен, немного затрудняюсь в правельной записи алгоритма. А именно из-за того что привык работать, как вы сказали "блоками" тут же нужна более детальная запись: 22 0300 St {Шаг_2} Cохранение m в ОП. (поправте меня если я ошибаюсь) 22- "это команда сохранения в ОП", а 0300- это ячейка "m". Если это так, то у меня возникает вопрос: 01- это команда ввода переменных "m" и "n", почему их нельзя объединить в один шаг? И на основании этого вопроса возникает другой, (шаг 5 и 6) что означает "безусловный переход"?? и можно ли опять же объединить эти действия путем одного вывода строчки "ПР<0 в противном случае ПР>=0" и конечный вывод результата уже под командой 02. Я понимаю что МиК устроен так и это целостная программа, но чисто теоритически на бумаге, можно скомпоновать алгорит и тем самым его немного упростить?.
Что касается самой программы, то за нее спасибо. Вопросы конечно есть, но как уже писали ребята их можно решить толкько прямой практикой, сразу что-то понять трудновато будет.
Зарания спасибо.

Почему выскакивает ошибка

Тебе нужно записывать в поле RA значение ячейки, откуда будет выполняться программа. Скорее всего, ошибка в этом, я тоже не сразу догадалась.

Немного непривычно

Сложновато с подобной детальной записью алгоритма. Но программа интересная. Думаю, больше практики мне поможет :)

На ваши вопросы по МиК:

С удовольствием отмечаю, что ваши вопросы становятся всё более предметными.
1. Давайте ограничимся пока программами, в которых нет условных команд и команд передачи управления (им соответствует как разобранный образец только задача 1).
Т.е. разберитесь пока только с командами: 01(in), 02(out),99(halt),10(add),11(sub), 12(cmp),21(ld),22(st),23(la).
Задавайте любые по ним вопросы. О регистре Z тоже пока можно не вспоминать.
2. Рустэм. По команде 01 процессор МиК умеет ввести за один раз (один шаг) только ОДНО число.Так он устроен и это надо принять как данность. Если Вам нужно ввести, например, три числа, заставьте процессор выполнить эту команду поочерёдно три раза. Только при этом не забыть, что ввод нового числа (оно попадает в сумматор) затирает в сумматоре старое число, которое нужно предварительно записать (сохранить) в ОП.
3. Александр. Анастасия совершенно права. Перед запуском программы, адрес первой её команды должен быть размещён в РА.
Впрочем, мы договорились интерпретатор пока не трогать.

Мик

Валерий Шахамболетавич Здравствуйте, я сейчас работаю с Мик уже поняла как работать с командами( это у меня уже получилась Ура!), но я не могу понять что такое А, и что в него надо записывать. Я вот хочу например сложить 2 числа, пусть будет 5 и 10, команду сложения здаю, но куда мне записывать эти числа?? прошу помогите

А - это адрес

А - это адрес ячейки.
Например чтобы сохранить значение сумматора в ячейку 0400 нужно ввести команду 22, а затем, в первом окошке А ввести две цифры ячейки (04), во втором окошке оставшиеся 2 цифры (00)

Значения записывай в любую

Значения записывай в любую свободную ячейку

так значит в А мы записываем

так значит в А мы записываем команду и число так

Не...команда записывается в

Не...команда записывается в окошко К ОП
В А записывается номер ячейки, а так как ячейка имеет 4 значный вид, то в первое окошко записывается 2 первых ее цифры, а во второе две последние))

все я поняла значит правильно

все я поняла значит правильно делала

спасибо большое

спасибо большое

Та не за что))

Та не за что))

наконец-то начал понимать

наконец-то начал понимать программу (это радует)

Добрый вечер))))

Здравствуйте у меня два вопроса))) Я разобрался как делать в МиК умножение, с вашей помощью конечно , а деление по такому же принципу делать?))) немного не понимаю) может посоветуете и подскажете что нибудь. Второй вопрос состоит в том что когда мы будем работать в паскале?) я немного подзабыл всю ситуацию этого ЯП )))

Валерия...

Давайте подробно.
Любая команда формата F1 обязательно состоит из кода операции (он занимает один байт памяти, выражается 2-значным числом и кратко обозначается как КОП) и адресной части (она занимает два байта памяти, выражается 4-значным числом и кратко обозначается как A).
Таким образом, буквой А мы обозначаем любой Адрес, указанный в адресной части команды формата F1 (такой, например, адрес как 0200 или 3333 в командах "22 0200" и "11 3333").
Т.е. можно сказать, что любая такая команда имеет вид: "КОП A".
Например, в команде сложения "10 2640" КОП это 10, а A это 2640.
Обратите внимание, что каждый байт команды представлен двумя цифрами. Цифр 6, поэтому команда имеет длину 3 байта.
В нашем последнем примере, для ввода в память МиК команды "10 2640" в первый из трёх предназначенных для неё байтов нужно ввести 10 -это КОП. Далее, 26 и 40 это то, что нужно ввести во второй и третий байты как единый адрес А (т.е. число 2640).
Соответственно, слева внизу на панели интерпретатора МиК имеются три поля, помеченные как КОП (одно однобайтовое поле) и A (два однобайтовых поля). В эти поля побайтово и заносится очередная команда.
Если всё же остались вопросы подойдите на большой перемене, всё покажу.

Станислав...

1. Да, деление по такому же принципу, основано на многократном вычитании.
2. Всему своё время.

Стас, ты поднял хорошую тему)

Стас, ты поднял хорошую тему) можно попробовать )

"КРАСИВЫЙ" КОД

Чтобы аккуратно вставить в ваш пост программный код, буквально наберите, например:
< pre>
0500)01
0501)22 0800
0504)11 0800
0507)02
0508)99
< /pre>
Т.е. просто заключите свой код между тегами < pre> и < /pre>.
Но не вставляйте в теги пробелов!(у меня они есть, поэтому пока не "красиво").
Попробуйте прямо сейчас, прямо этот пример!
Кстати, а что он вычисляет?

Вычитает из введенного числа

Вычитает из введенного числа это же число(в сумматоре) =0

 0500)01 // ввод числа с

  1.  0500)01 // ввод числа с клавиатуры. Число сохраняется в сумматор.
  2.  0501)22 0800 // запись числа в ячейку 0800
  3.  0504)11 0800 // вычитание числа в ячейке 0800 от числа в сумматоре.(очистка сумматора, т.к числа одинаковые)
  4.  0507)02 //вывод на дисплей полученного результата
  5.  0508)99 //стоп
  6.  

Как-то так.

Правильно, Ира

Вы первая. Правда есть недочёты (пост не озаглавили, а автоматически проставленный заголовок выглядит как часть кода, да и в чём результат программы неясно)

А Сергей вот на вставку кода

А Сергей вот на вставку кода не решился ...

я подумал что нужен ответ на

я подумал что нужен ответ на вопрос, а не код.. в дальнейшем учту)

Некоторая неточность, Ира. В

Некоторая неточность, Ира. В результате вычитания очищается не ячейка 0800, а сумматор. Я у Вас подправил.

Сергей!

Что значит "в дальнейшем"? Я же прошу "прямо сейчас". Дело на несколько секунд.
Мне важно знать кто это уже умеет!

Результатом программы будет

Результатом программы будет 0. И про сумматор буду иметь ввиду, спасибо.

0500)01     /вводим

  1. 0500)01     /вводим число(сумматор)
  2. 0501)22 0800/записываем введенное число в ячейку 0800
  3. 0504)11 0800/производим вычитание содержимого ячейки и сумматора
  4. 0507)02     /выводим результат(=0)
  5. 0508)99     /останавливаем программу

Ок, Сергей. Рустэм!

Почитайте выше и сделайте вот так:

  1. Рустэм Ачмиз

Можно немного конкретней?

Можно немного конкретней?

Это не к Вам Сергей

Это не к Вам Сергей относилось, а к Рустэму, который сбежал. Вам я ответил "ОК"

Валерий Шахамболетович!

Валерий Шахамболетович! Объясните, пожалуйста, неумной, как и где сделать такое оформление, я не пойму?

Добрый вечер.

Валерий Ш. я весь вечер на вашем сайте, что-то читаю, решаю. Не куда не пропадал.

Такой же вопрос.

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

Алгоритм.

  1.  1. 0500)01         // вводим число в (сумматор) ("In")
  2.  2. 0501)22 0800 // запись числа в ячейку 0800 ("St")
  3.  3. 0504)11 0800 // делаем вычитание ячейки и сумматора (сумматор обнуляется) ("Sub")
  4.  4. 0507)02         // вывод результата (0) ("Out")
  5.  5. 0508)99         // стоп ("Halt")

Разобрался)

алгоритм          

  1. 0400)?               //подготовим ячейку для Х
  2. 0402)01             //введем с помощью клавиатуры Х в сумматор
  3. 0403)22 0400    //копируем Х в ячейку 400
  4. 0406)23 0000    //копируем в сумматор число равное номеру ячейки, то есть 0
  5. 0409)11 0400    //отнимаем от 0 значение Х, сохраненное ранее в ячейке 400
  6. 0412)02             //выводим результат отнимания на дисплей
  7. 0413)99             //остановка алгоритма

возможно сам алгоритм покажется бессмысленным, но моей основной целью было попробовать оформить его как надо...

Справка

вбивать надо в поля программы.
см. Мик справку (прилагается с программой).

Целочисленное деление a и b

Алгоритм.
Чтобы получить частное a и b нужно из делимого вычитать делитель до тех пор пока делимое станет равно 0.
А количество операций вычитания и будет равно частному.

  1. 0100) ? /делимое
  2. 0102) ? /делитель
  3. 0104) ? /счетчик
  4. 0106) 01 /ввод делимого с клавиатуры
  5. 0107) 22 0100/запись делимого
  6. 0110) 01 /ввод делителя
  7. 0111) 22 0102/запись делителя
  8. 0114) 33 0500/на 0 делить нельзя
  9. 0117) 23 0000/берем 0
  10. 0120) 22 0104/обнуляем счетчик
  11. 0123) 21 0100/загружаем в s делимое
  12. 0126) 11 0102/вычитаем из делимого делитель
  13. 0129) 22 0100/запись полученного делимого
  14. 0132) 23 0001/берем 1
  15. 0135) 10 0104/начало счетчика
  16. 0138) 22 0104/записываем данные счетчика
  17. 0141) 21 0100/загружаем в s делимое
  18. 0144) 33 0150/если s=0, то продолжение программы начнется с 0150 ячейки
  19. 0147) 30 0126/возвращение к ячейке 0126
  20. 0150) 21 0104/загрузка в s данных счетчика
  21. 0153) 02 /вывод данных счетчика(частное)
  22. 0154) 99 /стоп

Стас, надеюсь теперь тебе понятно...
Может быть, можно реализовать рациональней...
У кого есть варианты, выкладывайте))

у кого есть другие варианты?

у кого есть другие варианты?

Отлично, Cергей!

Поздравляю! Наступаете на пятки лидеру курса - Насте (программа умножения). Хоть и заполночь, настойчивость вознаграждена и программа деления в целом получилась.
Но вот несколько замечаний:

  1. Строка 8 бессмысленна, т.к. команды с одресом 0500 у Вас не существует. При нулевом делимом результат непредсказуем;
  2. Ваша программа не обрабатывает случая деления с остатком (например 14 делить на 5 должно бы выдавать два результата: 2 - частное и 4 - остаток);
  3. Комментарий лучше отделять двойным слэшем ("//") как это принято во многих ЯП.

Для остальных добавлю, что во-первых, задачи типа умножения и деления - это на данной стадии повышенная сложность и их решение инициатива самих ребят. Тем не менее, если кто-то хочет присоединитья, то по такому же принципу можно бы решать и задачу возведения числа в натуральную степень, и нахождение НОД(m,n) и многое-многое другое. Кроме того, программу Александра можно подсократить. Работы хватит для всех!

Вы это сделали, Александра!

Поздравляю! Разделяю Ваш восторг - это и есть радость творчества.
Пара замечаний.
1. Научитесь вставлять "красивый код";
2. У Вас "машинная" форма представления кода. Она только для интерпретатора МиК. В наших записях мы ею не пользуемся. Каждая команда (не байт!) должна записываться в отдельной строке.
Успехов!