Да, уже хочется писать свои первые программы, но давайте идти последовательно. Для начала неплохо бы понять, что именно мы собираемся писать и зачем вообще это нужно.

Почему компьютеры всё ещё требуют от нас команды в виде кода, а не просто понимают нас с полуслова?

Да, в истории действительно бывали случаи, когда удар ладонью по компьютеру помогал его «починить», но уверяем вас: это скорее совпадение, чем надёжный способ разработки.

Итак, как же компьютер работает с командами?

Как обычные пользователи, мы часто даже не задумываемся о том, как вообще компьютер понимает наши команды. Нам легко привыкнуть к тому, что мы нажимаем кнопку, открываем приложение или вводим текст, а компьютер просто делает то, что от него требуется. И возможно кому-то в это будет трудно поверить, но всю эту работу, что вы видите на экране как результат - исполняет процессор. Думаем, вы как минимум слышали это слово. Именно он получает команды и выполняет их одну за другой. Когда мы запускаем программу, открываем приложение, нажимаем кнопку и видим результат на экране, в основе всего этого лежит работа процессора.

Если опуститься на его уровень, то окажется, что процессор вообще не понимает большие человеческие действия целиком. Он не понимает команд вроде "открой файл", "покажи сообщение" или "запусти игру" так, как понимаем их мы.

Давайте подумаем, как вообще можно что-то «сказать» процессору. Как передать ему информацию?

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

Здесь нам придётся совсем слегка окунуться в физику — но не переживайте, буквально на капельку.

У нас есть электричество. И именно оно, если сильно упростить, становится нашим первым способом общения с компьютером.

Как же это происходит?

Если говорить совсем просто, внутри процессора есть огромное количество крошечных элементов, на которых строится вся его работа. Эти элементы называются транзисторами. Через каждый из них может проходить электрический сигнал — или не проходить. Именно из таких простых состояний, а точнее их комбинаций компьютер потом собирает все свои вычисления.

Нам сейчас важно уловить только одно: такой элемент может быть либо в одном состоянии, либо в другом.

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

Небольшая аналогия для понимания: если мы возьмём три буквы, то сможем поставить их в разных последовательностях и получить разные слова. Например, из букв к, о, т можно получить «кот», «ток» и «кто». Буквы одни и те же, но порядок меняется — и смысл становится другим.

С электрическими сигналами похожая история: сами состояния очень простые, но их последовательность позволяет передавать разные значения.

Например, можно условно представить так:

  • если ток есть только в первом элементе, а в остальных его нет — это одна команда;
  • если ток есть только во втором элементе, а в остальных его нет — это уже другая команда;
  • если ток есть в первом и втором элементах одновременно — это третья команда.
  • и так далее.

То есть смысл не в какой-то одном элементе самому по себе, а в комбинации их состояний.

И вот если у нас есть всего три элемента, вы уже можете посчитать, сколько разных «слов» мы можем сказать компьютеру. Но в процессоре их, конечно, далеко не три, а миллионы и даже миллиарды. Именно поэтому из простых состояний «есть сигнал» и «нет сигнала» можно собрать невероятно сложные команды и вычисления.

Инженеры спроектировали процессор так, чтобы он умел распознавать определенные комбинации сигналов и по-разному на них реагировать. В такой комбинации может быть зашито довольно много информации. Например, в ней можно передать два числа и сразу указать, какую арифметическую операцию с ними нужно выполнить: сложить, вычесть, умножить или разделить.

То есть реакция на команды физически заложена в его устройстве. На уровне железа процессор спроектирован так, что одни комбинации электрических сигналов запускают один путь действий, а другие — другой. Процессор получает от нас определённую комбинацию, распознаёт её и выполняет заранее предусмотренную операцию. Затем он возвращает результат в том же базовом формате: где-то электрический сигнал появляется, где-то исчезает, и в итоге формируется новая комбинация.

А уже другие инструменты переводят эту комбинацию в человеческий язык: в текст, числа, картинки и всё то, что мы видим на экране.

Кто должен учить язык?

И что же получается? В теории человек мог бы сам переключать миллиарды транзисторов в разные состояния, хоть вручную. Только это было бы, мягко говоря, утомительно. А процессор...мы не можем научить его понимать нас даже на уровне попугая. Ему вообще всё равно что мы хотим от него😅 Он просто реагирует на сигналы так, как устроен физически.

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

Если процессор реагирует только на электрические сигналы, значит, в самом низу всё действительно сводится к двум состояниям: сигнал есть или сигнала нет. Позже человеку стало удобно обозначать эти состояния как 1 и 0.

Самые первые программы в каком-то смысле были очень близки к этому уровню - набору нулей и единиц. Например, если очень грубо представить простую программу, которая складывает три числа, она могла бы выглядеть примерно так:

0001 00000101
0010 00000011
0010 00000010
0011 00000000

Человек буквально задавал машине последовательности таких состояний: где должен быть сигнал, а где его быть не должно. Где-то это делалось переключателями, где-то перфокартами, где-то перфолентами, а позже — уже вводом чисел и команд в память компьютера.

Уже на таком маленьком примере видно, насколько это неудобно. А если программа становится длиннее, если в ней появляются условия, повторения, работа с текстом, памятью или файлами, то количество таких команд начинает очень быстро расти.

Именно поэтому со временем начали появляться более удобные способы общения с компьютером. Сначала - более понятные обозначения для машинных команд, а затем и полноценные языки программирования, на которых человек уже мог записывать свои мысли в гораздо более удобной форме.

Языки программирования

Лень — двигатель прогресса. Сомневаемся, что нам сейчас было бы приятно программировать напрямую через нули и единицы: без подсказок, без удобных слов, без права на ошибку. Поэтому человек постепенно пришёл к тому, что с компьютером нужно общаться на более понятном языке — не на уровне отдельных сигналов, а через команды, которые хотя бы немного похожи на человеческую логику. Если уж пришли к нулями и единицам - может и дальше можно пойти?

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

Их идея проста: человек пишет команды в более понятном для себя виде, а специальные программы уже переводят эти команды на язык, который способен выполнить компьютер. И программисту больше не нужно вручную думать о каждом электрическом сигнале о ноликах и единичках. Он может писать ближе к тому, как он мыслит.

Конечно, компьютер всё равно в конечном счёте работает с электрическими сигналами. А между человеком и процессором появляется несколько удобных «переводчиков». Мы пишем код на C#, а дальше специальные переводчики превращают его в инструкции, которые машина уже может выполнить.

Но вернемся к языками программирования.

Языки программирования делятся на разные группы. Например, есть низкоуровневые языки — они ближе к устройству компьютера и его внутренним командам. А есть высокоуровневые языки — они ближе к человеку и позволяют описывать задачи более понятно. Язык C# как раз является высокоуровневым.

Компилятор

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

Например, простая запись арифметического выражения на языке C# может выглядеть примерно так:

5 + 3

Для нас такая запись уже вполне понятна. Мы видим числа, видим саму операцию сложения и сразу понимаем, что от компьютера требуется.

Но, мы уже поняли, что процессор не понимает такую запись напрямую. Для него все это все еще слишком "по-человечески". Дальше язык все равно нужно как-то перевести в форму, которую компьютер действительно сможет выполнить.

Именно для этого и существуют специальные программы-переводчики. Их задача - взять код, который написал человек, и преобразовать его в более низкоуровневую форму, с которой система уже сможет продолжить работу.

Одно из ключевых понятий здесь - это компилятор.

Вы часто будете слышать фразы вроде «программа не скомпилировалась» или «произошла ошибка компиляции». А ещё часто будете видеть в редакторе кода надпись compiling, что значит «идёт компиляция».

Слово compile в английском вообще означает «собирать», «составлять», «компоновать из частей». То есть compiling — это буквально «сборка». Компилятор берёт ваш исходный код, проверяет его и собирает из него такую форму программы, которую дальше сможет выполнить компьютер или среда выполнения.

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

Промежуточный язык

Как вы думаете, в мире существует только одна модель процессора или их великое множество?

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

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

Именно поэтому перевод программы компилятором не всегда происходит сразу и напрямую в окончательный машинный код. Во многих современных языках между «человеческой» записью программы и командами для конкретного процессора есть ещё промежуточный этап. В C# это устроено именно так. Код на C# переводится не сразу в машинный язык конкретного процессора, а в специальный промежуточный язык. Его часто называют Intermediate Language, или сокращённо IL. Дословно это и означает «промежуточный язык».

Зачем нужен такой этап? Он позволяет отделить саму программу от конкретного устройства. Мы пишем код один раз, а дальше берется его промежуточное представление и подготавливает его к выполнению на той системе, где программа запускается. Благодаря этому один и тот же C#-код может работать на разных платформах, не заставляя нас вручную переписывать его под каждый процессор.

Получается вот что: мы написали программу, но заранее можем не знать, под какой именно процессор и систему её потом будут запускать. Процессоров много, они могут отличаться, и напрямую переводить программу под каждый вариант было бы неудобно. Поэтому код сначала переводится в промежуточный язык — IL. И дальше конкретная среда выполнения на устройстве берёт этот IL и переводит его в машинные команды, понятные именно этому процессору.

Фух, вот такой урок...да, пока ни одной строчки кода, но ничего страшного. Все эти вещи надо было проговорить - в будущем, когда вы будете сталкиваться с такими понятиями как IL компиляция, машинный код и так далее, теперь вы будете более готовы. А теперь, давайте кратко повторим, что мы сегодня узнали.

Фух, ну вот и всё. Надеемся, мы не утомили вас этой теоретической справкой. Она действительно нужна: дальше мы ещё не раз будем встречать слова компиляция, компилятор, машинный код, промежуточный язык, IL. И лучше познакомиться с ними сейчас, чтобы потом они не отвлекали от самого программирования.

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

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

Языки программирования бывают разными. Низкоуровневые языки находятся ближе к устройству компьютера и машинным командам. Высокоуровневые языки ближе к человеческой логике: они позволяют писать код более понятно и не думать о каждом отдельном сигнале внутри процессора. C# как раз относится к высокоуровневым языкам.

Компилятор — это специальная программа, которая переводит исходный код, написанный на языке программирования, в другую форму, пригодную для дальнейшего выполнения компьютером.

В C# компилятор сначала переводит наш код не сразу в машинный код конкретного процессора, а в промежуточный язык IL.

IL, или Intermediate Language, — это промежуточная форма программы: уже не обычный C#-код, но ещё и не машинный код конкретного процессора.

А дальше этот промежуточный язык переводится уже в машинные команды для конкретного устройства. То есть программа проходит два шага: сначала из C# в IL, а потом из IL в команды, которые понимает процессор. Благодаря этому нам не нужно вручную писать отдельную версию программы под каждый тип процессора.

Конечно, мы разобрали всё это очень поверхностно: не углублялись в физику, устройство процессора, электрические сигналы и работу компилятора. Но на первом уроке нам это и не нужно. Мы взяли ровно то, что сейчас будет полезно: общее понимание того, как программа проходит путь от кода до выполнения.

А теперь давайте переходить ближе к практике. В следующем уроке мы начнём с подготовки среды к программированию.

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

Тест 1

А вот и мы!

13

Что такое программа?

23

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

33

Зачем нужны языки программирования вроде C#?

Обсуждение урока

0
Комментарии видны всем. Чтобы участвовать в обсуждении, войдите или зарегистрируйтесь.
Модерация сообщества

Пожаловаться на комментарий

Расскажите модераторам, что именно требует внимания.