`

СПЕЦІАЛЬНІ
ПАРТНЕРИ
ПРОЕКТУ

Чи використовує ваша компанія ChatGPT в роботі?

BEST CIO

Определение наиболее профессиональных ИТ-управленцев, лидеров и экспертов в своих отраслях

Человек года

Кто внес наибольший вклад в развитие украинского ИТ-рынка.

Продукт года

Награды «Продукт года» еженедельника «Компьютерное обозрение» за наиболее выдающиеся ИТ-товары

 

Андрей Зубинский

О величии, могуществе, ужасе и мелочах

+1717
голосов

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

Говорят, очередная истерика опять сформировалась вокруг выхода какой-то очередной проходной версии какого-то очередного мобильного телефона. И это в 2012-м году :( Сказать по этому поводу мне нечего, посему побуду-ка я фриком. И побурчу.

Причём бурчать буду о "святом". О великом, могучем и ужасном языке C. Который остаётся языком №1, если судить по разным оценкам популярности и по более внятным критериям, например, по количеству поддерживающих язык инструментальных средств.

Давайте попробуем вычеркнуть всякую поэтику. Любые сравнительные степени. И говорить об инструменте без каких-либо придыханий. Особенно без стариковских восхищённых прошлым и разочарованных настоящим вздохов - "у меня есть советского производства молоток, так вот он до сих пор работает" (это было слабеньким мемом когда-то, который никто не форсил, и теперь мало кто помнит откуда вообще он взялся).

А ведь C всё больше напоминает этот самый, который "до сих пор работает", молоток из тех самых времён.

Не спешите в меня плевать. Рано.

Давайте задумаемся над простыми вещами.

Принято говорить, что C - это такой себе "высокоуровневый ассемблер", и что кто понял указатели и арифметические операции с ними, тот чуть ли не понял "железо".

Как и всё, что принято говорить, это и правильно, и не совсем, и, тем более, - не всегда.

Потому что если даже принять истинность утверждения "C - это высокоуровневый ассемблер", надо бы ответить на очевидный вопрос - а какой именно машины? 

Странно, но за прошедший год я прочёл много записей о С всяких блогов - и с восторженными откровениями, и с hate speeches, и ни один из авторов почему-то не начал с ответа на такой простой вопрос - а что мы знаем о виртуальной машине, исполняющей "язык ассемблера C"?

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

Итого, виртуальная машина C - фон Неймановская с линейной адресацией памяти. Это факт.

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

Для меня это три не факта. 

Но начну издалека и с несколько неожиданного в контексте.

Довелось мне влюбиться на старости лет в микроконтроллеры семейства PIC18, которые производит фирма Microchip. Когда-то, в одной из прошлых жизней, с PIC-контроллерами я имел дело, но это были другие времена, другие PICи (16-й серии). А вот в PIC18 раскрылась вся красота архитектуры.

PIC18 - гарвардская машина. Памяти программ и данных в ней размещаются в отдельных адресных пространствах. Что, в частности, означает - традиционные для фон Неймановских машин "фокусы" с переполнениями буферов и исполнением "левого" кода для гарвардских машин - штука невозможная. Когда-то для микроконтроллеров это было совершенно не важно. Но не в 2012 году, когда 8-ми (или 16-ти, смотря по чему судить - по разрядности обрабатываемых данных или по разрядности машинной команды) битовые машины на кристалле оснащаются очень даже "взрослой" периферией вроде Ethernet-контроллеров.

На самом деле у этой машины не два адресных пространства, а больше (есть ещё отдельное - для перепрограммируемого ПЗУ, EEPROM, и для некоторых моделей - ещё дополнительные, например, для доступа к буферам периферийных контроллеров). Но это уже не принципиально.

Память программ у этой машины вполне традиционная, с линейной адресацией (в некоторых пределах, не буду вдаваться в лишние детали).

А вот память данных - это что-то.

О чём и рассказывать лучше нетривиально.

Представьте себе - вы хотите сделать аппаратную поддержку защиты памяти N процессов (N - конечное значение, заранее известное, например, 15). Для малого вычислителя. Не претендующего на универсальность. Иными словами - выделить каждому процессу какое-то количество ячеек памяти и сделать так, чтобы из процесса при соблюдении минимальных правил написания программы на уровне машинных команд нельзя было "ударить" по памяти других процессов. Добавьте к этой задаче требование эффективной (опять же на уровне машинных команд) реализации межпроцессного обмена. И, наконец, примешайте ко всему этому быстрый доступ к управляющим регистрам кучи периферийных устройств. Опять же, на уровне машинных команд. Ну и, наконец, для полноты картины - всё это надо реализовать в RISC-процессоре с разрядностью обрабатываемого слова 8 бит, и с разрядностью машинной команды - 16 бит (у настоящих RISC-процессоров эти разрядности никогда не совпадают, потому что настоящий RISC-процессор должен исполнять команды за 1 такт, а как поместить, например, команду непосредственной загрузки регистра 32-битовыми данными в одно 32-битовое машинное слово?).

A?

Нетривиальная задача в итоге получается?

Весьма нетривиальная.

И вот что сделали архитекторы Microchip.

Чтобы "утрамбовать" в большинство однотактных команд всё, что возможно, иными словами - уместить в 16 битов команды как можно больше кодов команд, они разбили память данных на страницы по 256 байтов каждая. Очевидное решение. Любому программисту - очевидное. 256 байтов адресуются 8-битовым адресом, что оставлет ещё восемь битов из 16-ти машинного слова для кода команды. Пока всё просто и очевидно. Каждому процессу можно выдать свою страницу памяти, и за её пределы 8-битовым адресом он никак не выйдет.

Но в требованиях есть ещё возможность быстрого (то есть, с помощью того же 8-битового адреса) доступа к двум общим областям данных - одной для обмена между процессами и второй - для доступа к управляющим регистрам. Это уже сложнее. И для этого использован приём "схлопывания адресного пространства" с помощью дополнительного бита в коде команды. Если этот дополнительный бит установлен в единицу, 8-битовый адрес памяти данных в команде адресует ячейку выбранной страницы. А вот если в ноль - адресное пространство всех страниц "схлопывается", предоставляя тем же 8-битовым адресом доступ к первым 96 байтам первой страницы и последним 160 байтам последней страницы. То есть, вместо одной текущей выбранной страницы получается доступ к двум кускам двух страниц. Что позволяет однотактными командами быстро читать-записывать данные из этих кусков адресного пространства независимо от видимого в данный момент его фрагмента.

160 байтов последней страницы адресного пространства данных - они специальные. В них размещаются регистры управления процессором. В том числе и регистр, биты которого отвечают за выбор текущей страницы памяти данных. И три очень забавных одинаковых набора из семи регистров. Для реализации механизмов косвенной адресации в пределах всего адресного пространства данных, а не одной страницы. В пару регистров каждого такого набора можно загрузить 12-битовый адрес (12 битов - 4096 адресуемых ячеек памяти, размер страницы - 256 ячеек, следовательно, всего - 15 страниц), а пять оставшихся регистров представляют собой "интерфейсы" для выполнения операций чтения-записи без модификации этого адреса и, например, с автоматическим увеличением на единицу адреса после выполнения операции. Очень хитрый механизм косвенной адресации, ещё и в трёх экземплярах. Ну и ещё всяких интересных регистров есть в этой 160-байтовой области, которая во всех PIC18-контроллерах обязательно реализована и обязательно на 15-й странице памяти данных.

У кого повернётся язык назвать такую вычурную машину тривиальной? Особенно если добавить, что у неё есть 31-уровневый аппаратный стек (ещё одно адресное пространство), теневые регистры для быстрого переключения контекста и отдельный механизм дополнительного метода адресации памяти данных (он не важен в этом знакомстве)?

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

В общем, при некоторой практике (и с учётом доступности весьма "навороченных" PIC18) от этой машины начинаешь получать море удовольствия. До тех пор, пока... программируешь на ассемблере.

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

И, заодно, "вылезают" все огрехи C как языка низкоуровневого программирования.

Могу часть их перечислить:

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

2. Язык содержит соверешнно бесполезные для низкоуровневого программирования конструкции. Например, - битовые поля в структурах. В соответствии со стандартом C положение этих битовых полей в машинном представлении ничем не определяется, и потому зачем они нужны "в целом и основном" для низкоуровневого программирования - не совсем понятно;

Есть ещё множество нюансов, более относящихся к неудобствам, чем к фундаментальным недостаткам.

И всё это я хотел написать лишь с одной целью - очень нехорошо, что объявленный величайшим и ужаснейшим, хоть и заслуженно для определённых архитектур, язык программирования начинает косвенно диктовать условия системным архитекторам. Потому что становится очень скучно - все архитектуры постепенно становятся похожими друг на друга. А как же интеллектуальное удовольствие? :) Шучу. А как же ориентированные на прикладные области архитектуры? А как же архитектурная поддержка нужных и полезных задач?

И ещё хуже то, что за время существования C ничего лучше никто не придумал. Хуже - да. Хуже - это запросто. Одного C++ хватает, чтобы стало намного хуже.

Что, никто не занимается низкоуровневым программированием? Не верю. Больше того скажу - с ростом интереса к тому, что принято называть "умной пылью", с востребованностью Internet of Things, с доступностью "всепроникающего компьютинга", со всем этим спрос на эффективное низкоуровневое программирование будет расти. Никому, понимаете, не нужна "умная пыль" стоимостью $100 за "пылинку", ещё и требующая здоровенный аккумулятор для каждой "пылинки".

И чем же всё это удовольствие программировать? Так, чтобы всем в удовольствие было? Очень забавный вопрос, мне кажется.

(уткнулся в макроассемблер)

Откланиваюсь

Ready, set, buy! Посібник для початківців - як придбати Copilot для Microsoft 365

+1717
голосов

Напечатать Отправить другу

Читайте также

Было много попыток создать язык максимально приближенный к аппаратной платформе. Я в своей жизни столкнулся с PL/M и Ada для iAPX (86/88, 48, 51, 186, 432)

Для полноты картины, я бы предложил автору посмотреть на все выше изложенное с точки зрения архитектуры iAPX 432, как невольного прародителя всех встраиваемых микроконтроллеров. Мне, например только такой взгляд помог понять почему С а не Ада или Пролог.

да упаси Бог iAPX432 - прародитель встраиваемого :)

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

Неправильно. iAPX 51 использовала 80% архитектурных решений 432 платформы, переведенной из 32-х в 8 бит. И именно 432-я была ориентирована на встраиваемые системы, хотя сейчас трудно поверить в это. Встраиваемые в военную технику, отмечу.

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

Мне довелось поиграться с 432 "вживую" и на самом нижнем уровне имел возможность изучать ее архитектуру. А потом - плотно работать с 48-й, 51 и 186.

Мы, наверное, о чем-то разном. i8051 - развитие i8048. совершенно самостоятельная ветка. MCS-51, не iAPX 51

Уважаемый Андрей, ответ не потеме :) НО

Хотелось бы услышать ваши коментарии на среду программирования ДРАКОН и вообще по поводу такого визуального программирования, составления алгоритмов...

Очень интересно следить за вашими статьями и записями.

А нельзя ли всю эту красоту архитектуры воткнуть в DSL в каком-то language workbench ?

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

Про то, что все страшне становится жить - собственно, истерик то я и не заметил - так, немного качественного мусора от взрослеюших инфоботов, который все удачнее фильруется на старости лет.
Дабы добавить своего в равновесие, скажу что в обществах вольных каменщиков истерики скорее вызвали достижения ETH Züri в области умно-пылевой спинтроники. Вот бы кто побурчал на тему на качественном уровне :)

 

Ukraine

 

  •  Home  •  Ринок  •  IТ-директор  •  CloudComputing  •  Hard  •  Soft  •  Мережі  •  Безпека  •  Наука  •  IoT