Автор:
Sashok SamДрузья!
В прошлый раз мы с вами разобрали, что такое программа и что такое программирование. Сегодня мы продолжим обсуждение этого вопроса и посмотрим более детально, какие средства используются для создания программ.
Прежде всего, как вы помните, мы сравнивали компьютер с человеческим мозгом, а поведение компьютера с поведением человека. Мы обнаружили много общего между поведением человека и компьютера, когда речь идет об обработке и хранении информации. Однако, между этими процессами есть и очень существенная разница: человек может работать в условиях неполной информации и нечеткого задания, а компьютер нет.
Действительно, в жизни мы постоянно сталкиваемся с нечеткими инструкциями, например: Зайди, пожалуйста, в магазин по дороге с работы, купи колбаски, сыра... Вроде, простая просьба, однако задумайтесь над тем, как много информации осталось за кадром: в какой именно магазин, какой именно колбаски и какого именно сыра, сколько купить и т.д. Для человека это нормально, все, что неясно он домыслит исходя из своего предыдущего опыта. Кстати, иногда такое домысливание приводит к недопониманию (ну зачем же ты так много купил, ты что роту солдат накормить собираешься?). А все дело в том, что у двух участников разговора несколько разный предыдущий опыт, или осмысливают они его по-разному.
При создании инструкций компьютеру это абсолютно недопустимо! Инструкции должны быть заданы четко и недвусмысленно, ничего домыслить компьютер не может. Зато все однозначные инструкции компьютер будет выполнять четко, без колебаний, не привнося ничего постороннего. То есть его можно сравнить с абсолютно тупым, но очень исполнительным человеком.
- Напишите детальную инструкцию, описывающую, что нужно сделать, чтобы из комнаты, в которой вы сейчас находитесь дойти до кухни и поставить кипятиться воду. Если вы изучаете программирование не в одиночку, обменяйтесь с кем-нибудь инструкциями и попробуйте выполнить их. При наличии трех человек, третий может быть судьей и оценить, точно ли исполнитель следует инструкции, или добавляет отсебятину.
- Попробуйте усложнить задачу и описать, как добраться, скажем, от дома до работы, школы или института.
Если вы всерьез попытались выполнить задание, у вас наверняка возникли вопросы и проблемы. Это и неоднозначность человеческого языка, и вопросы о том, насколько детально надо расписывать инструкции, и другие. Связано это с тем, что человеческий язык изначально подспудно ориентирован на умение человека домыслить недостающее, а если составитель инструкции и исполняющий понимают ее по-разному, ничего толкового из этого не получится.
Как вы понимаете, компьютер в таких условиях работать не сможет. Поэтому обычные человеческие языки при написании программ не используются. Вместо этого применяются так называемые языки программирования, каждый из которых включает строго определенное количество абсолютно однозначных команд. Для всех таких языков создаются детальные спецификации команд, так что, по идее, никаких разночтений возникать не должно (правда, иногда они все равно возникают, но только в результате ошибок!).
Теперь самое время разобраться, а как же эти языки устроены, и, соответственно, как ими пользоваться. Прежде всего, надо помнить, что основная цель таких языков написание инструкций для компьютера. Выполнять их, соответственно, будет компьютер, а значит и запоминать тоже он. А тогда получается, что они должны быть удобны для запоминания и исполнения в компьютере. Именно такой подход в свое время и применили.
Чем мы теперь займемся? Правильно, начнем разбираться в том, как компьютер хранит и исполняет инструкции.
Прежде всего, представьте себе длинный стол. На столе лежат последовательно, одна за другой карточки с инструкциями и данными. Вы идете вдоль стола, просматриваете карточки строго по порядку и исполняете написанные на них инструкции сразу, как только становится ясно, что делать. Например, если на карточках лежит 2, +, 5, вы читаете 2 и понимаете, что с ним надо будет что-то делать, читаете + и понимаете, что к 2 надо будет что-то прибавить, читаете 5 и понимаете, что к 2 надо прибавить 5. Все! Команда понятна. Осуществляете сложение и получаете результат.
Это, конечно в несколько упрощенном виде, модель того, что происходит в компьютере. В этой модели вы играете роль процессора, а длинный стол с линейкой карточек роль памяти. Более подробное описание того, как это происходит на самом деле, может быть темой отдельного урока. Самое главное для нас сейчас то, что память действительно состоит из расположенных последовательно, одна за другой одинаковых ячеек (у нас это были лежащие на столе карточки), каждая из которых содержит либо инструкцию(+), либо данные(2, 5), а процессор идет по ним последовательно, читает оттуда инструкции и данные и исполняет полученные команды. Ячейки, из которых состоит память компьютера, еще называют байтами. Кстати, а какая оперативная память (RAM) у вашего компьютера? 256М? Это означает, что таких ячеек в ней чуть больше, чем 256 миллионов! Как разобраться в таком количестве ячеек и не перепутать с какими из них мы хотим работать? Для этого все эти ячейки перенумеровали, и теперь, зная номер интересующей нас ячейки, мы можем легко до нее добраться. Точно так же, как, зная адрес, вы легко можете найти нужный вам дом. Именно поэтому номера ячеек в памяти компьютера программисты называют адресами.
Более подробно описание устройства ячеек памяти и способов хранения в них чисел и инструкций мы отложим на будущее, пока же заметим только, что в этих ячейках все хранится в виде чисел и инструкции тоже, например, вместо + - 1, вместо - - 2 и т.д. Ну, вроде того, как школьник, захотевший зашифровать записку написал вместо А - 1, вместо Б - 2, и т.д. Вся записка будет состоять из чисел, но прочитать ее, зная, какое число какую букву обозначает, не представляет труда.
Теперь нам становится более не менее понятно, как написать программу. Мы просто должны поместить в ячейки памяти компьютера нужные инструкции и данные в виде чисел и отдать команду: Исполняй!. Такой вид программирования называется программированием в машинных кодах, а сами заносимые в ячейки памяти числа машинными кодами. Именно так составлялись программы для самых первых компьютеров. На них даже были специальные панели с кнопками, позволявшими заносить числа в ячейки памяти.
Перепишите детальную инструкцию из задания I с использованием машинных кодов. Для этого посмотрите, какие команды вам понадобились в задании I (например, повернуть налево, повернуть направо и т.д.), обозначьте их какими-нибудь числами (например, идти прямо - 1, повернуть налево - 2, повернуть направо - 3 и т.д., только помните все должно быть совершенно однозначно и детально ни одна команда не должна быть забыта!) и запишите последовательность действий не человеческим языком, а с использованием чисел вместо команд. Потом выполните то, что получилось.
Попробовали? Поняли, насколько тяжел был хлеб первопрограммистов?
Вот и они тоже это поняли и подумали: Перед нами компьютер, инструмент, предназначенный для переработки информации. И что же, мы должны вручную сами переводить для него +, - и все остальные операции в какие-то неудобоваримые числа?! Чепуха какая-то! В чем же проблема? А проблема в том, что компьютер понимает исключительно язык чисел, а человеку гораздо удобнее работать на обычном языке. Получается, что два участника процесса человек и компьютер говорят на разных языках. То есть, нужен переводчик, и почему-то роль переводчика взяли на себя программисты. Это неэффективно! Давайте лучше создадим для компьютера программу-переводчик, которая сама будет инструкции в нужные числа переводить. А мы будем писать более привычные +, -, *, или уж по крайней мере, аdd, subtract, multiply и т.д.
В результате этих размышлений процесс программирования коренным образом изменился. Теперь программист не должен был больше корячиться с числами, он мог записать свою программу более не менее в читабельном виде, потом запустить специальную программу-переводчик, которая переводила написанное в машинные коды, а уж потом приказать компьютеру исполнить получившиеся коды.
Такая программа-переводчик была названа ассемблером, а такое программирование программированием на языке ассемблера.
К сожалению (а, скорее к счастью, поскольку без монополии всегда лучше) компьютеры разрабатывались многими компаниями, они никак эти разработки между собой не согласовывали, и, естественно, у всех машинные коды получились разные. Например, у одной компании + - 1, - - 2, * - 3, а у другой, соответственно, + - 3, - - 10, * - 1. Поэтому говорят, что программирование в машинных кодах машинно-зависимое. Ассемблер тоже существенно не изменил эту ситуацию его задача состояла не в том, чтобы сделать программирование одинаковым для разных типов компьютеров, а в том, чтобы сделать его более удобным для каждого конкретного компьютера. Таким образом, программирование на языке ассемблера тоже машинно-зависимое.
С течением времени стали обнаруживаться определенные недостатки ассемблера. Первый и главный обнаруженный недостаток все-таки для каждой машинной команды надо писать ассемблерную команду. Это работает нормально для мелких программ, но, представьте себе, что вам предстоит решать большую задачу. Количество шагов в программе начинает выходить за пределы того, что нормальный человек может держать в голове. Так появилась идея создать язык программирования, который позволял бы, насколько это возможно, описывать необходимые действия с помощью команд, близких к человеческим языкам с использованием обычных математических формул, сколь угодно сложных, со скобками и т.д. Естественно, с этого языка программу надо переводить в машинные коды, что никто уже и не собирался делать вручную. По примеру ассемблера для этого создают специальные программы-переводчики, которые называются компиляторами. Кстати, перевод написанной человеком программы в машинные коды, осуществляемый компилятором называется кто бы мог подумать! - компиляцией.
У ориентированных на облегчение жизни человеку языков есть еще одно преимущество: поскольку они не ориентированы на систему машинных кодов какого-то определенного типа компьютеров, программы на них можно сделать машинно-независимыми. Если нам надо использовать одну и ту же программу на разных типах компьютеров, все, что требуется это переводчики (компиляторы) для каждого из используемых видов компьютеров. То есть, в идеальном варианте (что, к сожалению, в жизни бывает редко!), сколько бы разных видов компьютеров мы ни использовали, если у нас есть компиляторы для всех них, мы можем написать программу только один раз, а потом компилировать ее для каждого типа компьютеров.
Описанные выше человекоориентированные языки программирования называются еще языками высокого уровня. Языков таких существует много, но далеко не все из них стали популярны. Некоторые из популярных (или бывших когда-то популярными) Cobol, Fortran, Basic, Pascal, C, C++, Java.