Некоторые вопросы, касающиеся компиляторов и сборщиков

У меня в голове много основных вопросов. Мне нужно очистить их.

Утверждение 1. Компилятор преобразует удобочитаемые коды в объектные коды, а те преобразуются компоновщиком в машинный код (исполняемый).

Я прямо здесь?

В википедии написано, что

Object files are produced by an assembler, compiler, or other language
translator, and used as input to the linker.

Вопрос 1: ассемблер преобразует код на ассемблере (MOV A, BADD C) к машинному коду. В случае языка высокого уровня, такого как C++, он генерируется компоновщиком выше. Так что ассемблер нигде не используется. Так как же он может создать объектный файл, как написано выше?

Промежуточный код генерируется, чтобы заставить код работать на разных архитектурах.

Вопрос 2: файлы *.class (bytecode) создаются объектными файлами компилятора java? Если да, то можем ли мы сказать, что JVM, которая их запускает, является типом компоновщика (однако он не создает исполняемый файл)?

Вопрос 3: Когда мы компилируем программу на C++ в Turbo C++, мы получаем файлы *.obj, которые являются объектными файлами. Можем ли мы использовать их для генерации исполняемого файла в какой-то другой архитектуре?

2 ответа

Решение

Вопрос 1: да, ассемблер (as, gas, nasm, masm) компилирует инструкции по сборке в объектный код. В случае языков высокого уровня (H) компилятор компилирует H в любой другой язык (например, GHC, компилятор Glorious Haskell может производить C, но он также может производить C--, и была попытка (?) Произвести Java), или в объектный код через промежуточные шаги (или языки C-- или Core).

Промежуточный код может быть сгенерирован по многим причинам: 1. переносимость, например, файлы.class из java, p-код для Pascal 2. для облегчения оптимизации кода

Вопрос 2: файлы.class могут быть сгенерированы Java-компилятором, но Scala также генерирует файлы.class, а AspectJ (аспектно-ориентированный вариант) также создает файлы.class. Файлы.class не являются объектными файлами в том смысле, что им нужна виртуальная машина Java (и компоновщик Unix). ld не будет связывать файлы.class с файлами.o). Оригинальная JVM является интерпретатором файлов.class, но вы также можете компилировать java на лету.

Вопрос 3: Файлы Turbo C++ .obj (скомпилированные на 64-битной Intel) не были бы счастливы на машине Z80, если компилятор не имеет возможности кросс-компиляции для другой архитектуры, так что в случае Turbo C++ цель объектного файла не переносимость между платформами.

Объектные файлы представляют собой набор "машинного кода" (.text), инициализированных данных и символов, которые должны быть связаны.

Допустимый объектный файл может содержать только данные, например, байт-код.

Линкер - это программа, которая отображает целую группу объектов в виртуальное адресное пространство и определяет, к какому адресу относится какой-либо внешний символ. Это позволяет постепенно разрабатывать программы, так как нужно знать только интерфейс при вызове, например, функции printf. Компоновщик вводит реальный адрес printf внутри машинного кода на этапе компоновки. Это делается с помощью таблиц перемещения.

Это частично отвечает на вопрос № 3: нельзя напрямую использовать объектный файл, созданный другой архитектурой. Метод сопряжения не обязательно является двоично-совместимым. Также форматы obj -файлов могут быть разными. Но если кто-то действительно прикладывает усилия, он может написать обертки (скорее всего, в сборке), которые могут вызывать объекты, скомпилированные в Turbo C из Visual C. Если наборы команд, модели памяти и т. Д. Полностью отличаются, можно все же написать эмулятор, который вызывает функция. Подобные подходы постоянно используются при написании, например, сред для воспроизведения видео, которые могут вызывать некоторые устаревшие видеодекодеры, предоставляемые только в.dll.

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

Утверждение № 1 не является правильным. Компиляторы и ассемблеры преобразуют читаемый человеком код в машинный код, хотя некоторые компиляторы создают промежуточный язык для интерпретации (и / или компиляции "Just In Time"). На этом последнем этапе компиляция действительно означает то, что она должна - компиляция в машинный код.

Gcc содержит ассемблер и компоновщик. Можно скомпилировать int main() { printf("HelloW\n");} с gcc -S hw.c ассемблеру (hw.s), который является символическим машинным кодом, вставьте или замените некоторые строки и перекомпилируйте в объектный код gcc -c hw.s и, наконец, ссылка gcc -o hw.exe hw.o

Другие вопросы по тегам