Comments 29
Статье не хватает больше подробностей про каждый этап, имхо.
Очень неожиданно встречать статьи для начинающих.
Интерпретаторы С и С++ тоже существуют, например cling, однако носят скорее теоретическую ценность.
дополнение — ассемблер обычно вручную вызывать не надо
Сразу получаем объектник, а потом линкуем их в правльном порядке, с правильными библиотеками
Ух ты, я был уверен, что компиляция с промежуточным компилированием в ассемблер осталась далеко в прошлом.
А что мешает компилировать сразу в исполняемый код? И, как я понимаю, другие языки такой подход не используют, или я не прав?
Компиляторы, созданные в других традициях — например, MSVC — такого не делают; их можно попросить сделать листинг в ассемблере, но этот листинг нельзя потом скормить ассемблеру, чтобы получить объектный файл.
Причины такой двухстадийности gcc, по-моему, в его истории: у Столлмана получилось нормально сделать и лицензионно, и по сути результата — конверсию в задокументированный ассемблер на целевых платформах первого поколения (таких, как SunOS, HP-UX, AIX), но уже объектный формат имел сложновыясняемые и/или лицензионно недоступные особенности. Сейчас не нагуглилось, так что это обоснование только по воспоминаниям о прочитанном и услышанном около 20 лет назад. Потом же решили не менять этот подход, потому что он оказался вполне недорогим (по сравнению как с парсингом C++, так и с ценой преобразований программы в процессе компиляции), даже с промежуточным файлом.
И ещё вкусность — наличие полноценного ассемблерного исходника, который можно посмотреть и, если нужно, подправить под себя, очень помогло в росте белой хакерской культуры. Помню это по себе — если что не понимаешь, смотришь ассемблер и экспериментируешь и в нём тоже :)
С другими языками — опять же, кто компилирует:) Все языки из комплекта GCC (C, C++, Fortran, Ada...) или LLVM-based проходят такую фазу, обязательно или опционально. Аналогично, например, Go, но у него существенно свой ассемблер (причём на всех платформах; это мини-кошмар для системщика на x86 — кроме AT&T и Intel syntax, есть ещё Go syntax). В Unix мире много компиляторов переводят код своего языка на C, и уже этот результат компилируют, чтобы не заморачиваться после этого проблемами оптимизации; тогда тоже есть ещё фаза ассемблера.
Компилятор С исходно был сделан точно так же.
«60-е годы» это или чрезмерное обобщение, или надо говорить уже про 70-е. Под OS/360, например, компиляторы не использовали ассемблер в явном виде, у них был прямой «выхлоп» объектным файлом — а это середина 60-х.
Пока не знаешь, как процессор работает с памятью, как вызываются процедуры… все рассуждения так и останутся пассами рук, магией.
Для тех, кто хочет реально разобраться, лучший способ что-то понять — сгенерировать компилятором ассемблерный листинг и изучить его, для начала лучше с отключенными оптимизациями. Будет повод узнать про ассемблер, что и как. Потом разберётесь, как устроена реализация объектов ООП и пр. Это действительно красиво.
Потом станет понятнее, зачем нужны obj-файлы и связывание, а уж как работает загрузка исполняемых файлов…
… После этого вы станете презирать интерпретаторы ))
Ну, как бы, интерпретация и компиляция — разные вещи со своими плюсами и минусами.
И просто презирать интерпретаторы(кстати, какие именно) попахивает максимализмом юношеским.
Сгенерировав асм из плюсов мы лишь узнаем как реализует ООП конкретный компилятор плюсов.
Что не помешает другим компиляторам С++ делать это чуть иначе, а другим языкам принципиально по-другому.
Загрузка тоже отличается от платформы к платформе, ОС и т.п
Просто когда видишь, как производители CPU по крупицам улучшают предсказатели ветвления и бьются за каждый такт, становится грустно, что всё это богатство впоследствии успешно про$ирается программистами через высокоуровневые фронтенды, явы, дотнеты и виртуальные машины.
PS: сижу на ноутбуке с Core 2 Duo 1.6-1.8GHz и чувствую это почти физически )))
driver.s
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
movq %rax, %rdi
call _ZNSolsEPFRSoS_E
movl $0, %eax
popq %rbp
Зачем столько мусора в коде?
А что такое CXX compiler?
Процесс компиляции программ на C++