Я хорошо провел время, изучая дизайн TOC и компилятора, но еще не закончил, но чувствую себя комфортно с этими концепциями. С другой стороны, у меня очень поверхностные знания о сборке и машинном коде, и у меня всегда есть желание / необходимость соединить две стороны (представление кода в HLL и LLL), так как я изучаю C ++, уделяя большое внимание обсуждение производительности и оптимизации.
C ++ — статически типизированный язык:
Мой вопрос: наши переменные, когда они записаны в виде выражений в выражениях кода, все эти переменные (и другие объекты с идентификаторами) становятся во время выполнения простыми инструкциями адресации к позициям виртуальной памяти (для статических и глобальных) и адресация имеет отношение к адресу стека для локальных переменных?
Я имею в виду, что после успешной компиляции, включая семантическую и синтаксическую проверку, не разумно ли иметь дело с данными во время выполнения как с гарантированными объектами целевых байтов памяти, не задумываясь о каком-либо идентификаторе или какой-либо проверке, при этом таблица символов больше не нужна?
Если мой вопрос оказался типом вопросов, которые возникают из-за нехватки усилий для обучения (чего, я надеюсь, нет), просто сообщите мне об этом и скажите, где почитать. Если это так, то, честно говоря, потому что в настоящее время я концентрируюсь на C ++ и пока не имею возможности хорошо владеть языками низкого уровня, я заранее извиняюсь за это.
Да, в основном. Есть несколько деталей, которые сделают идентификаторы не только адресами или смещениями стека.
Сначала мы имеем в RTTI в C ++, что означает, что во время выполнения все еще может быть доступно имя по крайней мере типов. Например:
const std::type_info &info = typeid(*ptr_interface);
std::cout << info.name() << std::endl;
напечатает имя любого типа *ptr_interface
имеет.
Во-вторых, из-за способа, которым программа связана, символы из объектных файлов могут все еще присутствовать в исполняемом изображении. Например, у вас есть ядро Linux, которое может использовать обратную трассировку стека, включая имена функций. Также он использует знание имен функций, чтобы иметь возможность загружать и связывать модули. Подобная функциональность существует в библиотеке Gnu C, чем когда она связана, она может извлекать имена функций в следах стека.
В обычных случаях, хотя на код не влияют исходные имена переменных (но компилятор, конечно, будет выдавать код, подходящий для типа переменной).
Вы на месте. После компиляции в машинный код больше не существует понятия идентификатора переменной (или типа переменной). Это просто байты в определенном месте. Который местоположение было определено компилятором (при компиляции) на основе имени переменной или компоновщиком (при компоновке) в случае глобальных переменных.
Конечно, может быть полезно сохранить такую информацию, как идентификаторы, для целей отладки. Это именно то, что означает «компиляция с отладочной информацией»: когда вы это делаете, компилятор каким-то образом вставляет (избыточные) идентификаторы в сгенерированный код, так что отладчик может получить к ним доступ. Или поместите их в отдельный файл рядом с ними; детали этого зависят от формата отладочной информации.