Я в настоящее время прокладываю себе путь посредством современной Реализации Компилятора Andrew Appel в Java, и я прав вокруг точки, где я создаю промежуточное представление низкого уровня.
Первоначально, я решил быть нацеленным на JVM и проигнорировать весь материал машины низкого уровня, но в интересах изучения вещей, о которых я не знаю много, я изменил мнение. Это изменяет мой IR, потому что предназначение для JVM позволяет мне (более или менее) махают моими руками созданию вызова метода или построению объекта.
Книга Appel не вдается в подробности ни о какой определенной архитектуре машины, таким образом, я хотел бы знать, где я могу узнать все, что я должен знать для движения дальше.
Вещи, что я в настоящее время знаю, что должен знать:
Какую систему команд использовать. У меня есть два ноутбука, на которых я мог разработать; у обоих есть процессоры Core 2 Duo. Мое текущее понимание - то, что x86 процессоры главным образом используют ту же систему команд, но они не все точно то же.
Влияет ли операционная система на шаг генерации кода компиляции, или абсолютно ли это зависит от процессора. Например, я знаю, что что-то является особенным в генерировании кода для работы 32-разрядного по сравнению с 64-разрядной платформой.
Как организованы стековые фреймы и такой. Когда использовать регистры по сравнению с помещением параметров на стеке, сохраните вызывающая сторона по сравнению с сохранением вызываемый, всем этим. Я думал бы, что это будет описано наряду с системой команд, но до сих пор я не видел эту конкретную информацию нигде. Возможно, я неправильно понимаю что-то здесь?
Ссылки на ресурсы вместо ответов отлично одобрены.
Большая часть набора инструкций x86 является общим для всех процессоров - можно с уверенностью сказать, что оба ваших процессора имеют один и тот же набор инструкций, за исключением, возможно, инструкций SIMD, которые, вероятно, не будут очень полезны для вас при реализации простого компилятор (эти инструкции обычно используются для ускорения работы мультимедийных приложений и т.п.). Набор инструкций приведен в руководствах Intel - 2A и 2B, в частности, содержат полный список инструкций и их поведения, хотя другие тома заслуживают внимания.
При генерации кода пользовательского пространства ch Когда дело доходит до системных вызовов, значение операционной системы имеет значение. Например, если вы хотите, чтобы программа выводила что-то на терминал в 64-битном Linux, вам необходимо выполнить системный вызов:
rax
, чтобы указать, что это запись системного вызова
. rdi
, чтобы указать, что следует использовать стандартный вывод (1 - файловый дескриптор для стандартного вывода) rsi
rdx
syscall
после установки регистров (и памяти). Возвращаемое значение write
сохраняется в rax
.
В другой операционной системе может быть другой номер системного вызова для write
, может быть другой способ передачи аргументов (системные вызовы Linux x86-64 всегда используют rdi
, rsi
, rdx
, r10
, r8
и r9
в указанном порядке для параметров с номером системного вызова в rax
), и может иметь разные системные вызовы в целом.
Соглашение для обычных вызовов функций в Linux аналогично - порядок регистров rdi
, rsi
, rdx
, rcx
], r8
и r9
(все то же самое, за исключением использования rcx
вместо r10
), с дополнительными аргументами в стеке и возвращаемое значение в rax
. Согласно эта страница , регистры rbp
, rbx
и r12
до r15
должны сохраняться во всех функциях. звонки.Вы, конечно, вольны составить собственное соглашение (если не выполняете системный вызов), но это затрудняет вызов из кода, сгенерированного или написанного другими.
Я не могу ответить на все ваши вопросы; но
Как организованы кадры стека и тому подобное. Когда использовать регистры против помещения параметров в стек, сохранение вызывающего абонента против сохранения вызываемого абонента, все это . Я бы подумал, что это будет описано вместе с набором инструкций , но пока я нигде не видел эту конкретную информацию. Может быть, я Вы что-то не понимаете ?
В общем, на эти вопросы нет правильных ответов. Вы можете использовать любые соглашения о вызовах, какие захотите ... если только вы не хотите взаимодействовать с кодом других людей. Для обеспечения взаимодействия компиляторы стандартизируют двоичные интерфейсы приложений. Насколько я понимаю, Itanium C ++ ABI в последние годы стал популярным стандартом. Попробуйте начать с этого.