English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

гость
1 / ?
назад к урокам

Программирование в абсолютном двоичном коде

Первые программисты писали в абсолютном двоичном коде: каждая инструкция & каждый адрес в сыром двоичном коде. Одна инструкция может выглядеть как 01100101 00001010 — код инструкции & адрес памяти в двоичном виде.

Проблема спагетти-кода

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

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

Результат: путь выполнения через программу прыгал на кажущиеся случайными места. Хэмминг назвал это 'банкой спагетти'. Путь потока управления, нарисованный на бумаге, выглядел ровно как запутанные спагетти.

Маршруты выхода

Два немедленных улучшения: восьмеричная нотация (группировка двоичных цифр по трём) & шестнадцатеричная (группировка по четырём, использование A–F для значений больше 9). Они сократили ошибки в написании, но не решили фундаментальную проблему адреса.

Символическая ассемблерная программа (например, SAP (Symbolic Assembly Program) IBM & SOAP (Symbolic Optimizing Assembly Program) на IBM 650) позволила программистам писать имена инструкций (ADD, MOVE) & символические метки адресов вместо двоичного кода. Ассемблер переводил в двоичный код во время ввода, автоматически управляя назначением адресов.

SOAP выполнял дополнительную оптимизацию: он располагал инструкции на вращающемся барабане так, чтобы следующая инструкция прибыла в головку чтения ровно когда предыдущая завершилась — кодирование с минимальной задержкой. SOAP даже компилировал себя: программа A обрабатывалась как данные для создания B, B запускалась на A для измерения того, насколько самокомпиляция улучшила его.

Дерево синтаксиса & иерархия языков

Библиотеки & перемещаемый код

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

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

Неопубликованные отчёты фон Неймана (широко распространённые) описывали необходимые приёмы программирования. Первая опубликованная книга по программированию (Wilkes, Wheeler & Gill, EDSAC, 1951) кодифицировала эти методы.

Объясните, почему библиотеки с абсолютными адресами создавали проблему масштабируемости, & как перемещаемый код её решил. Какое конкретное свойство абсолютных адресов вызывало конфликты, & что означает технически 'перемещаемый'?

Развилка дизайна языка

FORTRAN (1957, IBM) & ALGOL (1958, международный комитет) представляют две философии дизайна, которые произвели радикально различные результаты.

FORTRAN

Джон Бэкус возглавлял проект FORTRAN (FORmula TRANslation) в IBM. Цель дизайна: сделать язык лёгким в использовании для учёных & инженеров. FORTRAN принимал математическую нотацию, которая чувствовалась естественной для своих пользователей: A = B + C * D вместо ADD B, C; STORE T; MULTIPLY T, D; STORE A.

FORTRAN выжил более 60 лет. Он остаётся в активном использовании в научных вычислениях, гидродинамике, моделировании климата & вычислительной физике. Хэмминг отметил эту долговечность как доказательство успешного дизайна.

ALGOL

ALGOL (ALGOrithmic Language) был разработан комитетом логиков & компьютерных учёных, нацеленных на математическую строгость: логически чистый, формально определяемый язык. Нотация Backus-Naur Form (BNF) для описания грамматик была изобретена для спецификации ALGOL.

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

Иерархия языков

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

Четыре критерия языка программирования Хэмминга

Хэмминг дистиллировал урок FORTRAN vs ALGOL в четыре критерия для успешного языка программирования:

1. Легко учиться — новичок может стать продуктивным быстро

2. Легко использовать — рутинные задачи требуют минимальных формальностей

3. Легко отлаживать — ошибки создают осмысленные, находимые сообщения об ошибке

4. Легко использовать подпрограммы — переиспользование & абстракция не требуют героических усилий

Он добавил структурное наблюдение: человеческий язык содержит около 60% избыточности; письменный язык около 40%. Языки с низкой избыточностью (как APL) создают элегантные однострочники, которые эксперты находят красивыми & новички находят непрозрачными — & которые содержат необнаружимые ошибки, когда один символ меняет значение.

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

Применить четыре критерия Хэмминга к языку программирования, который вы хорошо знаете. Оценить каждый критерий 1–5 (5=отличный). Затем определить какой критерий, если усилен, больше всего улучшит язык — & объяснить, что конкретное изменение может выглядеть.

Психологический vs логический дизайн языка

Хэмминг вернулся к контрасту FORTRAN/ALGOL как к уроку в институциональной & человеческой динамике, не только дизайне языка.

FORTRAN был разработан психологически — для людей, которые его будут использовать, специально для учёных, которые думают в математической нотации. ALGOL был разработан логически — для формальной правильности & теоретической элегантности.

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

Он привёл APL как крайний случай: логически элегантный, выразимый однострочниками, со своим собственным специальным набором символов. Эксперты его любили. Нормальные программисты нашли его нечитаемым. Один символ может молча трансформировать значение программы. APL имеет небольшое преданное сообщество & почти нулевое основное использование.

Аргумент человеческой избыточности: разговорный язык ~60% избыточен (повторённый контекст, уточняющие слова, предсказуемая структура). Письменный язык ~40% избыточен. Эта избыточность служит обнаружению ошибок — люди ненадёжны, так что язык эволюционировал для несения достаточно повторённой информации для ловли & исправления ошибок. Язык с низкой избыточностью удаляет эту сеть безопасности.

Иерархия компилятора

Хэмминг описал наслаивание компилятора/интерпретатора: программа может читать язык более высокого уровня & переводить его на более низкоуровневый. Наложите эти слои — каждый переводит на один уровень вниз. На вершине: язык, ориентированный на область, который эксперты в области (биология, финансы, физика) пишут естественно. На дне: машинный код. Каждый переход — это компилятор или интерпретатор.

Предсказание выживаемости языка

К 1993 году Хэмминг видел, как много языков преуспели & потерпели неудачу. FORTRAN (1957) выжил. ALGOL (1958) потерпел неудачу. COBOL (1959) выжил десятилетия в деловых вычислениях. LISP (1958) выжил в исследованиях AI. PL/I (1964) попытался унифицировать всё & потерпел неудачу.

Используя различие психологического vs логического дизайна Хэмминга & его четыре критерия, объясните, почему один язык, который вы знаете, преуспел & один потерпел неудачу (или терпит неудачу). Ваше объяснение должно определить конкретные человеческие факторы, которые направили принятие или отклонение — не просто технические свойства.

Повторяющийся паттерн

Глава истории программного обеспечения Хэмминга содержит повторяющуюся структуру:

1. Болезненное ограничение существует (абсолютные адреса, двоичная нотация, неуправляемый код)

2. Кто-то изобретает слой абстракции, который скрывает ограничение

3. Абстракция позволяет новый масштаб, который создаёт новые болезненные ограничения

4. Повторить

Двоичный → восьмеричный/шестнадцатеричный → символический ассемблер → FORTRAN → структурированное программирование → объектно-ориентированные языки → языки, ориентированные на область. Каждый слой разрешает самую острую боль предшественника, пока вводит новый класс проблемы.

Проблема спагетти-кода (абсолютные адреса) привела к символическому ассемблеру. Большие программы ассемблера привели к FORTRAN. Большие программы FORTRAN привели к структурированному программированию & затем объектной ориентации. Лекция Хэмминга закончилась до этих более поздних переходов, но паттерн продолжается.

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

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