Share
Языки и методы программирования - лекция-3: архитектура компьютера и программы на языках высокого уровня
Лекция курса "Языки и методы программирования"
Лекция-3: архитектура компьютера и программы на языках высокого уровня
- Коммутационные панели (коммутационные доски, commutation plugboard)
- "Программирование" ЭНИАК перенастройкой коммутационных панелей
- Повышение производительности труда в области перенастройки компьютера под задачу: концепция хранимой программы
- Архитектура Джона фон Неймана
- Концепция хранимой программы
- Повышение производительности труда в области создания (разработки) программы: язык ассемблера, компиляторы, языки программирования высокого уровня
- Машинный код
- Язык ассемблера
- Программа в памяти
- Языки программирования высокого уровня
- Компилятор
- Язык Си: переменные, размещение переменных в памяти, ассемблерный код для инструкций языка Си, выполнение простой программы по шагам
- Просмотр ассеблерного кода программы на Си в отладчике Qt Creator
- Инструменты кросс-компиляции программы на Си для архитектуры MIPS32, просмотр ассемблерного кода исполняемого файла с objdump
- Итоги
- Задания для самостоятельной работы
Anton
Transcript
76 slides
-
Коммутационные панели • Электромеханические счетные машины Германа Холлерита в начале
20-го века умели считать статистические показатели на больших объемах данных, записанных на перфокартах • Логика счета определялась специальной электрической схемой: для разных показателей требовалось составить разные комбинации электромеханических переключателей (реле) • Для часто используемых показателей такую схему можно было спаять целиком и установить в машину в качестве готовой составной детали • Но для ситуаций, когда логику счета требовалось менять относительно часто, такой подход оказался слишком негибким • В следующих версиях машин для удобства перенастройки схемы стали использовать т. н. коммутационные панели (commutation plugboard) -
• Развитие и распространение — в статистических перфокартных машинах IBM
(и конкурирующих производителей) • Но не только • Один из первых электронных вычислителей общего назначения ENIAC использовал аналогичный подход -
ENIAC (1945) • en.wikipedia.org/wiki/ENIAC • Electronic Numerical Integrator and Computer
• Первый программируемый электронный цифровой компьютер общего назначения • Общего назначения: полон по Тьюрингу • Построен: 1945 год • Элементная база: электронные вакуумные лампы и реле -
ENIAC (1945) • Процесс программирования компьютера выглядел как процесс переподключения
проводов • (уже есть программа, но называть процесс программирования вычислителя «внесением программы в компьютер» не вполне корректно — скорее здесь процесс частичной пересборки компьютера под программу) • Т.о. программа здесь — это алгоритм, определяющий логику вычислений, который может быть переведен на язык электрической схемы • Финальная форма программы — электрическая схема • Компьютер здесь выступает как своеобразный электрический конструктор (полуфабрикат), который можно пересобрать по схеме -
• Процесс перенастройки вычислителя под программу был довольно трудоёмким и
мог занимать несколько дней • На этапе планирования проекта предполагалось, что задачи (программы) будут меняться не слишком часто и после перенастройки вычислитель будет долгое время гонять один и тот же алгоритм на разных данных • Плюс играл роль фактор спешки — среди прочих задач задача обеспечить удобство ввода программы была не в приоритете -
Дополнительно отметим • Процесс написания программы и конвертирования программы в
схему подключения проводов вычислителя явным образом отделен от процесса перенастройки компьютера под выполнение программы • Процесс написания программы — труд в чистом виде интеллектуальный • Процесс перенастройки компьютера по схеме — труд в чистом виде физический • В процессе перенастройки просто так (как в любимой IDE) провода туда-сюда не попереключаешь, чтобы посмотреть, как та или иная комбинация подключений повлияет на то, как будет работать алгоритм — программу писали и «отлаживали» в голове и на бумаге задолго до запуска -
Архитектура Джона фон Неймана • Сложность перенастройки ENIAC для каждой
новой задачи являлась существенным и заметным ограничением, которое в следующих проектах вычислителей решили устранить • Над одним из проектов работал Джон фон Нейман • Он пришел в команду разработчиков ENIAC на поздней стадии проекта в качестве консультанта, быстро вник в суть дел, потом внутри команды произошел конфликт, • Джон фон Нейман продолжил работу над проектом нового универсального вычислителя в другом месте с новой командой, в качестве руководителя -
• К реализации проекта подошли академически: значительное внимание уделили проработке
теоретического фундамента и этапу проектирования • В рамках этой работы было опубликовано несколько отчетов, в которых были сформулированы базовые принципы, которые должны быть реализованы в проекте вычислителя • Эти принципы были хорошо приняты научным и инженерным сообществом, легли в основу практически всех последующих проектов вычислительной техники • Сохранились в истории под именем Джона фон Неймана как «фоннеймановская архитектура» или «архитектура Джона фон Неймана» (хотя автором идей и документа был не он один) • В соответствии с принципиальной позицией Джона фон Неймана они стали общедоступными — не были запатентованы -
Концепция хранимой программы • Среди прочего, в отчетах были сформулированы
принципы и рекомендации создания программ общего назначения, был разработан язык блок-схем, была предсказана важнейшая роль библиотек готовых подпрограмм • Одним из важных принципов фоннеймановской архитектуры является концепция хранимой программы • Каждая инструкция вычислителя получает численное представление — машинный код • Программа, представляющая собой последовательность инструкций, размещается в памяти вычислителя на общих правах с данными — как последовательность чисел (нулей и единиц) -
• Коды операций и другие участки машинного кода, размещенные в
памяти вычислителя, будучи логически представлены нулями и единицами, • Фактически представляют собой закрытые и открытые транзисторы, которые выстраивают электрические цепочки связей -
• В зависимости от того, как расположены нули и единицы
в машинном коде текущей инструкции, внутри вычислителя будут активированы те или иные электрические цепи, в той или иной последовательности соединяющие между собой аппаратные вычислительные блоки • Труд по переконфигурированию ЭВМ переподключением проводов теперь происходит в автоматическом режиме • Коммутационная панель больше не нужна -
• Реализация концепции хранимой программы позволила радикально уменьшить время перенастройки
компьютера при смене рабочей программы • (повысить производительность труда оператора ЭВМ) • Вместо ручного переподключения проводов на коммутационной панели, программу можно было сохранить на внешний носитель (перфокарту или магнитную ленту), • А потом загрузить на выполнение во внутреннюю память вычислителя («загрузить программу в компьютер» — теперь так говорить вполне корректно) — так же, как это уже делали с данными -
• Труд оператора теперь: подключить внешний носитель к вычислителю и
инициировать процесс загрузки машинного кода программы в память для выполнения • В современном исполнении: набрать команду в терминале, нажать кнопку «запустить» в среде разработки, два раза кликнуть на исполняемом файле, нажать иконку на экране смартфона, кликнуть на ссылку в браузере и т. п. • Процесс «перенастройки» вычислителя для выполнения новой программы (загрузка программы в память) настолько слился с процессом повседневной эксплуатации вычислителя, что мы его не замечаем -
• Труд системного администратора (оператора ЭВМ, отвечающего за загрузку и
работу программного обеспечения на аппаратном обеспечении) по форме сложно отличить от труда разработчика программного обеспечения (оба сидят за компьютером, нажимают кнопки, запускают программы) • По содержанию тоже есть множество пересечений: системный администратор может писать скрипты или программы, а разработчик программного обеспечения сам регулярно запускает какие-то программы и т. п. -
Существенная разница: • Продукт труда разработчика ПО — программное обеспечение,
т. е. идея • Продукт труда системного администратора (оператор ЭВМ, devOps) — могут быть услуги или материальные блага, создаваемые посредством обслуживаемого им аппаратного обеспечения -
• Однако, с производительностью труда по загрузке ПО на вычислитель
теперь всё более- менее понятно • Рассмотрим теперь ближе труд по созданию программного обеспечения: что он из себя представляет, какие есть возможности сократить затраты времени на него -
Повышение производительности труда в области создания (разработки) программы: язык ассемблера,
компиляторы, языки программирования высокого уровня -
Машинный код • Первое время набивали вручную на перфокартах •
Но мыслить «нулями и единицами» человеку проблематично • Так или иначе, у машинного кода имелось представление, читаемое человеком -
• Памятка программиста, 1960-е годы. Цифровой (машинный) код «Минск-22» •
ru.wikipedia.org/wiki/Машинный_код -
Язык ассемблера • Символьное представление полей машинной инструкции, которое может
читать и писать человек • Взаимнооднозначное соответствие • Но некоторые детали уже скрываются за удобным синтаксисом (например, из ассемблерной записи может быть не вполне очевиден максимальный размер численных параметров) • По большей части: одна инструкция в машинном коде — одна строка в программе на ассемблере • (но не всегда: появляются т. н. мета-команды, облегчающие разработку) -
Язык ассемблера • Т.к. машинный код представлен в памяти в
виде чисел • и код программы на ассемблере тоже может быть представлен в виде чисел (кодированный текст) • А компьютер у нас — универсальный вычислитель, который может путем формально-логических и арифметических преобразований превращать одни числа в другие, • А правила соответствия между числами машинного кода и числами, представляющими программу на ассемблере, с точки зрения формальной логики однозначны и довольно просты, • Можно написать такую компьютерную программу, которая автоматически превратит текстовое представление программы на языке ассемблера в её машинный код -
Язык ассемблера • Если у разработчика программного обеспечения будет персональный
доступ к компьютеру: экран, клавиатура и возможность сохранять набранный внутри компьютера текст, • он сможет писать код на языке ассемблера и запускать его на ЭВМ самостоятельно, не привлекая оператора (взять на себя труд оператора) • Необходимое время для разработки программного обеспечения при этом заметно сократится • (возрастет производительность труда в области разработки ПО) -
Язык ассемблера • Программа, превращающая программы на языке ассемблера в
машинный код, — транслятор • Программа, превращающая машинный код в программу на языке ассемблера, — дизассемблер -
Кстати • Некоторые пытливые умы посещает вопрос рано или поздно:
как появился первый транслятор ассемблера в машинный код? • Набивание программы в машинном коде по современным меркам кажется невероятной «дичью» с запредельной трудоёмкостью • Кажется невероятным, чтобы кто-то действительно мог так разрабатывать реальную программу • Так, что «проблему» первого транслятора можно мысленно приблизить к проблеме «курицы и яйца» -
Кстати • Но это на первый взгляд, если не быть
знакомым с эволюцией вычислителей • По сравнению с коммутационными досками машинный код — это очень хороший вариант по удобству и производительности • Очевидно, для первого транслятора дырявили машинный код • На второй взгляд: другого варианта просто быть не может • (todo: но было бы хорошо проверить точно) -
Языки высокого уровня • После ручного пробития машинного кода на
перфокартах язык ассемблера кажется замечательным вариантом • Но даже в ассемблере (в современных вариантах), мы видим, начинают появляться т. н. мета-команды • Мета-команды — это такие команды, которые в программе на языке ассемблера занимают одну строчку, а транслятор превращает их, например, в две строки в машинном коде • Это может быть связано с перемещением чисел туда-сюда в памяти (достаточно большое число может потребоваться предварительно разрезать на куски, программисту легко ошибиться, а транслятор за него это сделает без ошибок как надо) -
Языки высокого уровня • По мере накопления опыта становится понятно,
что при разработке программного обеспечения простые задачи постоянно повторяются с некоторой вариативностью • Но на ассемблере приходится писать раз за разом блоки, состоящие из множества строчек, похожих по смыслу, но отличающихся в деталях • Появляется соблазн обозначить эти конструкции через более короткие конструкции, но при этом сохранить вариативность -
Языки высокого уровня • По существу: придумать новый язык, более
лаконичный, чем ассемблер, но который можно перевести на ассемблер • Так, чтобы последовательность команд на ассемблере в реальности выполняла то, что назначено смыслом лаконичной конструкции на языке высокого уровня -
Языки высокого уровня • При этом детали ассемблерной реализации могут
быть стерты из контекста лаконичного языка • (например, не важно какой регистр использовать для промежуточных вычислений — главное, чтобы он был свободен; или не важно, какая ячейка памяти будет выбрана для переменной) • Абстрагироваться от деталей — перейти на более высокий уровень абстракции -
Языки высокого уровня • «Высокий уровень» — по уровню абстракции
всё, что выше ассемблера • Иногда языки «высокого уровня» могут делить на «высокий» и «низкий» уровень внутри них самих, • т. е. какой-то язык высокого уровня может оказаться языком низкого уровня по сравнению с другим языком • В целом, это профессиональный сленг, а не строгая классификация -
Компилятор • Компилятор (сборщик) — это программа, которая переводит программу,
написанную на одном языке программирования, в программу, написанную на другом языке программирования • Обычно раньше: переводит программу на языке высокого уровня в программу на языке ассемблера • Правила перевода (соответствия) между языками должны быть сформулированы так, чтобы перевод можно было осуществить цепочкой формально-логических преобразований • В таком случае, их сможет осуществить вычислитель -
Языки высокого уровня • Кроме сокращения времени на написание кода
благодаря лаконичности и уменьшения вероятности ошибиться (сокращения времени на отладку) • Сокращается время на перенос программ между вычислителями с разной архитектурой, т. е. разным набором машинных кодов и разными языками ассемблера (кросс-платфоменность) • Некоторое время при переходе на новую аппаратную платформу было нормальной практикой писать с нуля весь набор необходимых вспомогательных программ и подпрограмм • С появлением платформо-независимых языков высокого уровня, для переезда на новую платформу стало достаточно портировать компилятор -
Языки высокого уровня • Fortran (1957, IBM) — один из
первых языков высокого уровня ru.wikipedia.org/wiki/Фортран • Си (англ. C) (1972, Bell Labs, Деннис Ритчи) — один из старейших языков высокого уровня, не теряющий актуальность («хоронителей» обычно «хоронили» раньше), фундамент ИТ-инфраструктуры ru.wikipedia.org/wiki/Си_(язык_программирования) • GCC (GNU C Compiler в составе GNU Compiler Collection, 1987, Ричард Столлман) — компилятор языка Си с исходным кодом, опубликованным под лицензией GPL. На текущий момент поддерживает множество аппаратных архитектур, один из популярнейших компиляторов и важнейших проектов для современной инфраструктуры ИТ gcc.gnu.org/wiki/History ru.wikipedia.org/wiki/GNU_Compiler_Collection -
Qt Creator: посмотреть ассемблерный код • Скомпилировать проект • Поставить
точку останова (на последней строке) • Запустить в режиме отладки • Перейти в меню: Отладка > Уровень инструкций • (если не запустить в режиме отладки, это меню не будет доступно) • (в нашем случае ассемблерный код сгенерирован для архитектуры x86_64) -
• movl — загрузить константу в память (одна команда) •
mov — загрузить значение из памяти в регистр или из регистра в память • %rbp — какой-то регистр (скорее всего указатель стека) • (%rbp - 0xс) — адрес в памяти переменной a • (%rbp - 0x8) — адрес в памяти переменной b -
Для архтитектуры MIPS • Набор инструментов для кросс-компиляции • (когда
на одной архитектуре компилируете код для другой архитектуры) • (например: на компьютере x86_64 компилируете код для MIPS) -
Ubuntu + gcc + MIPS • В репозиториях два пакета
(ставьте любой): - gcc-mips-linux-gnu - gcc-mipsel-linux-gnu ] apt-get install gcc-mipsel-linux-gnu После установки запускать: • gcc: mipsel-linux-gnu-gcc • objdump: mipsel-linux-gnu-objdump -
gcc + MIPS ] mipsel-linux-gnu-gcc prog-add.c -g -o prog-add-mipsel •
prog-add.c — имя файла с исходным кодом программы • «-o prog-add-mipsel» — указать имя исполняемого файла (появится в текущем каталоге после компиляции) • «-g» — включить в исполняемый файл отладочную информацию (если опцию не указать, то файл будет скомпилирован, будет работать и его можно будет дизассемблировать, но на следующем шаге вместе с ассемблерным кодом не будет видно исходный код Си) -
prog-add-mipsel: формат файла elf32-tradlittlemips [...] Дизассемблирование раздела .text: [...] 004007b0
<main>: #include <stdio.h> int main(void) { [...] int a = 9; 4007cc: 24020009 li v0,9 4007d0: afc2001c sw v0,28(s8) int b = 3; 4007d4: 24020003 li v0,3 4007d8: afc20020 sw v0,32(s8) int c = a + b; 4007dc: 8fc3001c lw v1,28(s8) 4007e0: 8fc20020 lw v0,32(s8) 4007e4: 00621021 adduv0,v1,v0 4007e8: afc20024 sw v0,36(s8) printf("%d + %d = %d\n", a, b, c); [...] ] mipsel-linux-gnu-objdump -S prog-add-mipsel -
gcc + x86_64 • Всё полностью аналогично • Просто запускать
gcc и objdump как «gcc» и «objdump» • gcc создаст исполняемый файл для архитектуры x86_64 • objdump дизассемблирует в инструкции x86_64 -
• Определение — это такое качество предмета, которое сохраняется в
изменениях предмета • Попробуем определить программу -
Программа — это идея, • отвечающая на вопрос, что будет
делать вычислительный механизм, • сформулированная на специальном языке, • который путем формально-логических преобразований может быть переведен в машинный код вычислителя. -
Машинный код, • будучи перенесен (записан) на специальный носитель, может
быть подключен к вычислителю в качестве составной детали, • после чего вычислитель произведет действия, заложенные в программе, • Т.е. воплотит идею программы в жизнь -
Язык ассемблера и машинный код • Машинный код сам по
себе тоже является программой • Но обычно используется более удобное представление — язык ассемблера • Удобное для чтения человеком • Можно сказать, что это человекочитаемое представление машинного кода (с оговорками) • Программа на языке высокого уровня обычно сначала переводится на язык ассемблера • После этого из языка ассемблера уже генерируется машинный код -
Язык ассемблера и машинный код • По форме программа состоит
из последовательности инструкций (команд) • Инструкция состоит из логики (код команды) и данных (параметры команды) • Данные могут быть объединены с логикой в рамках одной инструкции или разнесены по разным ячейкам памяти (обычно работает смешанный вариант) -
Самостоятельно • Установите Qt Creator • Установите набор инструментов gcc
• Запустите тестовый код — простую математическую формулу • Например: значение полинома 2*x^2 + x + 41 при разных x = 7, 14, 129 • Посмотрите ассемблерный код дизассемблированный из исполняемого файла • (можно просто x86_64, но лучше и с вариантом MIPS) -
Самостоятельно • Подумайте в контексте истории о модном технологическом тренде
— программы (ИИ), которые пишут другие программы • Где их место цепочке технологий или они из неё выбиваются как нечто совсем новое, чего еще раньше не было • Какова будет их роль и влияние (если предположить, что хотя бы один проект будет реализован до рабочего состояния) • Получится ли благодаря им исключить человека из процесса разработки программного обеспечения, как об этом мечтают адепты