Вы путаете несколько вещей.Я перенастраиваемый компилятор, такой как gcc, и другие универсальные компиляторы компилируют файлы в объекты, затем компоновщик позже связывает объекты с другими библиотеками по мере необходимости, чтобы создать так называемый двоичный файл, чтобы операционная система могла затем читать, анализировать, загружать загружаемые блоки и запускать выполнение.
Вменяемый автор компилятора будет использовать язык ассемблера как вывод компилятора, после чего компилятор или пользователь в своем make-файле вызывает ассемблер, который создает объект.Вот как работает GCC.И как clang работает, конечно, но теперь ООО может создавать объекты напрямую, а не просто сборку, которая собирается.
Гораздо больше смысла создавать отлаживаемый язык ассемблера, который генерирует необработанный машинный код.Вам действительно нужна веская причина, как JIT, чтобы пропустить шаг.Я бы не стал использовать инструментальные цепочки, которые идут прямо к машинному коду только потому, что они могут, их сложнее обслуживать и, скорее всего, они будут содержать ошибки или занимают больше времени для их исправления.
Если архитектура такая же, то нет причин, почемуу вас не может быть общего набора инструментов для генерации кода для несовместимых операционных систем.инструменты GNU, например, могут сделать это.Различия в операционных системах не определяются по определению на уровне машинного кода, большинство из них находятся на высокоуровневых библиотеках языка C, которые можно создавать для графических окон и т. Д., Не имеют ничего общего с машинным кодом или архитектурой процессора, для некоторых операционных систем то же самоеC-код, специфичный для операционной системы, может использоваться на mips, arm, powerpc или x86.где архитектура становится специфической - это механизм, который вызывает реальные системные вызовы.Специальная инструкция часто используется.и машинный код в конечном итоге используется да, но нет причин, почему это не может быть закодировано в реальной или встроенной сборке.
И это приводит к тому, что библиотеки, даже fopen и printf, которые являются общими вызовами C, в конечном итоге вынуждены делать системный вызов, так что большая часть кода поддержки библиотек может быть совместима между языками высокого уровня систем, поэтому потребуетсябыть частью системы и архитектуры для последней мили.Вы должны увидеть это в источниках glibc или в newlib, например, в других библиотечных решениях.Как примеры.
То же самое верно для других языков, таких как C ++, как и для C. Интерпретируемые языки имеют дополнительные уровни, но их виртуальные машины - это просто программы, которые находятся на похожих уровнях.
Низкоуровневое программирование не означает машинуни на ассемблере это просто означает, что к какому языку программирования вы используете доступ на более низком уровне, ниже приложения или ниже операционной системы и т. д.