* "Магия ПК" 2000 №5(27), С. 43-45.
Итак, вопреки всякой логике вы всё же решили научиться писать программы. Причем именно писать, а не "ваять" наскоро что придется и как придется. Неважно, что сподвигло вас на это решение, - стремление получить престижную профессию, врожденная любознательность, желание выделиться среди друзей или взломать сервер Пентагона. В любом случае вам придется пройти тернистый путь, лишь изредка перемежающийся минутами подлинного торжества.
О том, с чего нужно начинать учиться программированию, сказано немало. Неоднократно писала об этом и "Магия ПК". Однако многое из того, что советуют профессиональные педагоги, на практике оказывается более чем спорным. А потому взглянем на эту проблему еще раз - с позиций практики.
Антиутопия компьютерной педагогики
Во многих современных учебниках по программированию настоятельно рекомендуется начинать с освоения какой-либо системы визуального программирования - Delphi, C++ Builder, Visual C++ или Visual Basic. При этом приводятся следующие аргументы:
• визуальные среды позволяют быстро получить привлекательный результат;
• все современные системы программирования ориентированы на объектный подход; к чему учиться устаревшим парадигмам, если ООП - наиболее современен?
• визуальные среды - профессиональный инструмент, знание которого пригодится в будущей работе.
Оспаривать эти доводы трудно, и тем не менее они более чем странны. Начнем с того, что получение учащимся осязаемого результата действительно весьма важно для последующего обучения, но при этом отнюдь не безразлична ценность самого результата. В конце концов, выигрыш в чемпионате по Quake - тоже результат, вот только ценность его близка к нулю.
Практика показывает, что люди, начавшие учиться с освоения визуальных технологий, в дальнейшем с большим трудом привыкают к тому, что сущность программирования заключается не в перетаскивании управляющих элементов по рисованному окну. Элементарные понятия, связанные с исполнением программы как последовательности инструкций, осознаются ими с большим трудом. Не случайно пользователи Windows затрачивают на изучение программирования значительно больше сил, нежели те, кто знакомился с компьютером во времена более примитивных операционных систем.
Еще более спорным является тезис о целесообразности начинать изучение программирования непосредственно с объектного подхода. Спору нет, ООП - прогрессивная и современная технология, однако это - не панацея. И сейчас во многих случаях решения, диктуемые этим подходом, оказываются далеко не оптимальными. Но не это главное. Главное заключается в том, что идея программного моделирования предметной области, лежащая в основе концепции ООП, слишком сложна для восприятия без предварительной подготовки. И если понять сам принцип восприятия мира как множества взаимодействующих сущностей при наличии определенного философского фундамента еще возможно, то осознать, как исполняется объектная программа на ЭВМ, - почти непосильная задача.
Наконец, третий тезис также не бесспорен. Во-первых, потому что изучение программирования лишь на несколько процентов состоит в освоении конкретной среды, а большую часть времени и сил приходится тратить на осознание общих принципов, формирование специфики мышления, ознакомление с типовыми подходами и приемами. Во-вторых, практика показывает, что профессиональному программисту труднее всего работать именно в той среде, с которой начиналось его обучение.
Это легко объяснимо - на начальной стадии каждый из нас делает массу ошибок, формирует множество неверных представлений, которые впоследствии пересматриваются, однако оставляют заметный след в нашем сознании. И, вторично оказываясь в той же ситуации, с которой ему приходилось сталкиваться в процессе обучения, специалист как бы теряет накопленные профессиональные навыки и непроизвольно ищет решение на основании давних ассоциаций новичка. По крайней мере таково его первое движение, а именно оно играет основную роль в принятии разработчиком ключевых проектных решений.
Однако главное заключается в другом: использование визуальных сред, во всяком случае правильное использование, полностью заслоняет от пользователя архитектуру машины, специфику выполнения ею написанной программы. А между тем, для того, чтобы программирование не превращалось в мистический процесс укрощения своенравного компьютера, а оставалось ремеслом, профессией, очень важно, чтобы разработчик хорошо понимал принципы выполнения своей программы. И с этой точки зрения обучение на основе визуальных сред и ООП бессмысленно, ибо человек, наученный таким образом, подобен монтеру из известной рекламы - работающая программа невольно вызывает у него восклицание: "Ё-мое, что ж я сделал-то?"
"К четырем прибавить два..."
Интересно, что идея начинать обучение с конца характерна только для программирования. В самом деле, никто ведь не пытается преподавать релятивистскую механику прежде законов Ньютона! Все науки прошли долгий путь развития, множество ошибочных и неточных теорий, некорректных экспериментов. Школьник, изучая их, как бы повторяет за несколько лет всё, что делало человечество в течение тысячелетий. Бессмысленная трата времени? Нет! Двигаясь таким образом, ученик как бы сам приходит к тем же выводам, что и его великие предшественники.
Отчего же не начать программирование с начала? Нет, не с тумблеров и светодиодов разумеется, но с фон-неймановской архитектуры и понятия программы как последовательности исполняемых команд. Естественно, рассматривать принципы машинной организации "всухую", особенно если вы молоды и честолюбивы, совсем неинтересно. А потому, если уж начинать писать программы, то лучше всего сразу осваивать язык ассемблера.
Парадокс? Ведь Ассемблер по сей день считается едва ли не самым сложным из языков программирования. Однако на самом деле он имеет немало достоинств именно с точки зрения "обучения с нуля".
Во-первых, Ассемблер прост. Это не просто сенсационное заявление - это факт. Архитектура компьютера, будь то IBM-совместимый ПК или промышленный контроллер от Toshiba, как правило, сравнительно проста - память, регистры, стек. Несколько видов адресации да условные и безусловные переходы. Порождаемый каждой командой эффект обычно тривиален для понимания, а потому весь процесс изучения сводится к механическому запоминанию мнемоник инструкций. Если последние достаточно логичны, как, например, в Ассемблере процессоров Intel, учить машинный язык совсем несложно.
Во-вторых, изучая язык Ассемблера, учащийся волей-неволей вынужден сталкиваться с архитектурными особенностями своего компьютера. Такие понятия, как сегменты памяти, порты или escape-последовательности из чисто абстрактных категорий становятся инструментами для решения прикладных задач. Более того, понимая, можно ли реализовать ту или иную программу на Ассемблере, хотя бы теоретически, программист ощущает пределы возможностей машины, осознает, что можно требовать от компьютера, а что - нет.
Еще одно несомненное преимущество заключается в том, что переход от Ассемблера к языку высокого уровня значительно проще, чем наоборот. Осваивая C++ или Паскаль, ассемблерщик представляет себе, как работает та или иная конструкция на уровне машинного кода, во что она будет скомпилирована. Соответственно, он понимает свою программу, не боится ее.
Кроме того, и это психологически важно, Ассемблер благодаря своей универсальности рождает уверенность, что в случае необходимости отдельные фрагменты программы могут быть написаны или отлажены на самом низком уровне. А это - пусть эфемерная, но всё же гарантия того, что любая техническая проблема может быть решена, пусть большой кровью, но наверняка.
И, наконец, даже сейчас язык Ассемблера иногда бывает полезен и даже незаменим. И не только при программировании для спецмашин, контроллеров и другого "экзотического" оборудования, но и при разработке некоторых программ для ПК - драйверов, системных утилит, фрагментов операционных систем, при реализации алгоритмов, требующих повышенной производительности.
Очень часто основным недостатком Ассемблера называют громоздкость написанных на нем программ и сложность их тестирования и отладки. Действительно, работать с десятками и сотнями тысяч строк кода самыми примитивными средствами нелегко. Но именно так рождается то упорство, та бесконечная настойчивость, без которой самый одаренный человек никогда не сможет стать хорошим программистом. Ибо для хорошего профессионала мало придумать красивый алгоритм, нужно еще уметь при необходимости дни и недели "выуживать" из него неуловимую, непонятную ошибку.
"Мы всё начнем сначала…"
Если вы вознамерились начать учиться программированию с освоения Ассемблера, то небесполезно будет знать несколько азбучных истин, способных существенно облегчить учебный процесс.
Во-первых - о книгах. Учиться программированию проще и эффективнее с книгой в руках, но достать в наше время хорошую книгу по Ассемблеру непросто. Чаще всего попадаются либо справочники по архитектуре ЭВМ, либо толстые учебники с массой примеров, лишающие читателя всякого удовольствия от самостоятельного творчества и мешающие воспринимать принципы построения программ, затмевая их массой ненужных деталей. Начинающему лучше всего подойдет простой справочник по системе команд процессора и функциям операционной системы. Удобным компьютерным вариантом такого пособия может служить система TechnoHelp.
Не стоит пытаться писать на Ассемблере под Windows. Вообще, желание сразу получить красивые окошечки мало совместимо с последовательным изучением программирования. В данном же случае вы рискуете утонуть в массе ненужных и непонятных деталей.
Первое, с чем следует ознакомиться, - организация ЭВМ: регистры, память, стек. Первые несколько программ логично написать максимально просто - несколько пересылок между регистрами и памятью, запись и чтение из стека, передачи управления, вызов процедур. Работу программ можно изучить по шагам (в режиме трассировки) в любом доступном отладчике - Turbo Debugger, AFD и даже MS Debug.
Далее можно переходить к функциям DOS - выводу на экран, работе с файлами, распределением памяти. Последний шаг - программирование внешних устройств: динамика, таймера, параллельного и последовательного порта. Имея в запасе такой инструментарий, можно переходить к реальным задачам. Интереснее, но и сложнее всего разрабатывать резидентные программы и драйверы: овладев этим искусством, вы можете смело переходить к языкам более высокого уровня.
Доброе напутствие
Чтобы закончить с общими рекомендациями по тому, как проще всего освоить язык Ассемблера, стоит дать еще несколько конкретных советов:
1. По мнению большинства ассемблерщиков, лучший транслятор для IBM PC - TASM фирмы Borland. Версия, поскольку вы вряд ли будете писать очень сложные программы, решающего значения не имеет.
2. Знание Ассемблера - не вершина, а только первая ступень к профессионализму. Если вам удалось в совершенстве овладеть этим языком, вы скорее всего хорошо представляете себе устройство компьютера и базовые принципы исполнения программ в однозадачной операционной системе. Это - необходимые навыки, но не более того.
3. Закончив изучать Ассемблер, познакомьтесь с одним из процедурных языков, лучше всего Паскалем или C++ в режиме расширенного C. Только поняв особенности конструкций высокого уровня, овладев технологией структурного программирования можно начать готовиться к штурму ООП.
4. Разрабатывая программы на Ассемблере, не стремитесь как можно шире использовать макросредства и специальные директивы компилятора. Во-первых, этим вы, скорее всего, сведете к нулю переносимость своей программы, во-вторых, для целей обучения значительно полезнее, чтобы каждая инструкция, исполняемая в программе, была написана вами собственноручно.
5. Не "срисовывайте" готовые примеры. Возможно, есть люди, способные обучаться на чужом опыте эффективнее, чем на своем, но только мне такие не известны. Естественно, модификация работающих примеров позволит получать результат значительно быстрее, чем при работе "с нуля", только познавательный эффект от нее будет, увы, невелик.
6. Стремитесь не только узнать, но и сделать: доделывайте работу до конца. Разработать хорошую программу на Ассемблере не просто, но если вы справитесь с этой задачей, быстрота и компактность вашего детища станут достойной наградой за труды.
Дерзайте, леди и джентльмены!
Константин Хайт
OCR: fir-vst, 2016
Рисунок: Игорь Копельницкий ©