--------------------------------------------------------------------------- [10-09-2012 11:11:40] О пользе ЯВУ в задаче генерации процессорного кода Структурный код ведь на самом деле не для красоты придумали. Для удобства? В конечном итоге да, но это не совсем та формулировка. Просто есть целый ряд синтаксических конструкций, увеличивающих универсальность кода. Изначально есть просто процессорный код, в нем тоже можно писать вручную. Я кстати когда-то довольно долго ассемблировал код вручную, под 6502, на бумаге (пока мы не обнаружили, что там в бейсике встроен ассемблер %) Так вот главная польза от ассемблера - вовсе не символьные коды инструкций и регистров, а, главным образом, автоматическое вычисление смещений для переходов. Руками это делать очень неудобно - добавишь инструкцию куда-нибудь, и уже надо корректировать все переходы вокруг нее Aвтоматическое вычисление переходов и адресов данных - это первый метод автоматизации программирования. A следующий - как раз структурные конструкции - for/while и т.п. Потому как в ассемблере для каждого перехода надо руками ставить метки, и эти метки должны быть уникальные, иначе возникают проблемы с copy-paste. Обычно это уже элемент языков высокого уровня, но в masm есть локальные метки, автоматические циклы и т.п., т.е. вопрос с уникальными метками можно обойти и без Си. Следующая фишка - автоматизация передачи параметров в функции и математическая запись расчетов, т.е инфиксная арифметика. Это в каком-то виде тоже есть в ассемблерах, только довольно криво. Ну, слишком сложно оформляется и странно работает, неудобно в общем. Hо это больше вопрос реализации - можно было бы сделать и лучше, просто ассемблеры лет 20 уже как забросили развивать. Еще одна полезная фишка - автоматическая аллокация регистров. Hа PC регистров мало, на все переменные не хватает. Hо если их автоматически назначать, то в теории можно более эффективно использовать регистры, сохраняя удобную форму записи, т.е. к переменной обращаться по имени, а компилятор пусть сам думает, в регистре она или в памяти. Hо даже это реализовано в рамках ассемблера - только inline asm в gcc правда. Там хитрый асм с поддержкой шаблонов, может автоматически подставлять переменные в код. К сожалению, там много ограничений, но опять же, это проблемы реализации а не асма. Таким образом, практически, кроме инфиксной записи и типов, Си ничем не лучше асма. A как раз польза этих вещей не так однозначна, как кажется. Инфиксная запись вызывает кучу ошибок из-за сложности приоритетов, ассоциативности, преобразований типов и т.д. A вот зато _не_ пользоваться инфиксиной записью в Си сложно - надо создавать временные переменные и придумывать им имена, а в асме это проще. И типы - в теории они придуманы чтобы компилятор мог обнаруживать ошибки, но реально они по большей части мешают - заставляют вручную писать приведение типа. Ошибки тоже иногда все-таки ловятся, но имхо больше вреда чем пользы. Так что в Си по сравнению с асмом для облегчения программирования в общем-то практически ничего нет. Зато в С++ есть классы и шаблоны и неймспейсы. Классы обеспечивают сокращенную запись кода - в паскале правда для аналогичной цели есть оператор with, но в Си такого нет. А шаблоны вообще позволяют генерировать код на ходу, в зависимости от параметров. И еще там есть полиморфизм и наследование - в сочетании с шаблонами за счет этого получаются действительно хитрые трюки. Вот тут типы как бы оказываются действительно нужны, хотя имхо зря разработчики смешали несвязанные вещи в одной конструкции. Т.е. у них классы - это структуры данных, и они же - семантическая информация, позволяющая косвенным образом выбирать код для работы с конкретным объектом. Другими словами, что log( int ) и log( double ) - это совершенно разные функции, а в программе вызов выглядит одинаково, это весьма удобно. Где-то в другом месте поменял тип переменной, и из одного и того же "log(x)" уже скомплилось что-то другое. Но вот почему скажем объекты разных классов (скажем, инстансы шаблона класса) нельзя считать одним типом с т.з. полиморфизма?.. Или наоборот, объекты одного класса обратывать по-разному в зависимости от дополнительной информации (например, в зависимости от аллокации с выравниванием и без). В С++ это все навешено на все ту же структуру классов и часто приходится классы оформлять для использования совершенно не по назначению. В общем, куда-то не туда пошел прогресс :) Не говоря уже, что для многих фич процессора в ЯВУ просто нет соответствующих понятий (для флагов и стека, например). Вообще, мне давно хочется увидеть классификацию конструкций языков программирования с т.з. универсальности кода и способов преобразований кода. Т.е. С++, например, позволяет взять сишную программу с глобальными переменными и алгоритмом в main(), дописать вокруг нее пару строк, и получить уже класс, которым можно обратывать несколько таких объектов параллельно. Но к сожалению, С++ в плане рефакторинга тоже не идеал - часто приходится вручную синхронизировать имена в разных местах. Cкажем, если переименовать класс, то надо вручную переименовать и конструктор... и вообще все упоминания Но к сожалению мода сейчас ушла в совсем другую сторону - питоны всякие, которые на чистом железе работать в принципе не могут. И, что забавно, потихоньку возникло новое поколение ассемблеров и Си-образных языков - теперь для GPU Только они намного кривее того, что уже было сделано для CPU, потому что мода не позволяет тратить на это ресурсы :) 1) Aвтоматическое вычисление переходов и адресов данных 2) структурные конструкции - for/while и т.п. 3) автоматизация передачи параметров в функции 4) математическая запись расчетов, т.е инфиксная арифметика. (+автосохранение промежуточных результатов) 5) автоматическая аллокация регистров 6) Классы обеспечивают сокращенную запись кода (+автоматическая конструкция/деструкция объектов, но польза этого сомнительна) (+перегрузка операторов, но это редко используется и ничем не лучше именованных функций) 7) Шаблоны позволяют генерировать код, с подстановкой параметров 8) Полиморфизм и наследование (поиск по типам параметров, в т.ч. по шаблонам) 9) Неймспейсы (в т.ч. автоматические в классах и шаблонах) позволяют использовать локальные имена