Подтвердить что ты не робот

NASM Vs GAS (Практические отличия)

Я не пытаюсь спросить о том, что Intel против AT & T war (спорная точка, теперь, когда они поддерживают синтаксис Intel) или спрашивают, какой из них лучше "лучше", я просто хочу знать практические различия в выбирая один или другой.

В принципе, когда я собирал некоторые базовые сборки x86 несколько лет назад, я использовал NASM без каких-либо причин, кроме книги, которую я читал, тоже, что заставило меня твердо, но непроизвольно в лагере NASM. С тех пор у меня было очень мало причин использовать сборку, поэтому у меня не было возможности попробовать GAS.

Учитывая, что оба они поддерживают синтаксис Intel (что я лично предпочитаю) и должны теоретически, по крайней мере, создавать один и тот же двоичный файл (я знаю, что они, вероятно, не будут, но смысл не должен быть изменен), каковы причины в пользу того или другого?

Это параметры командной строки? Макросы? Немагнитные ключевые слова? Или что-то еще?

Спасибо:)

4b9b3361

Ответ 1

Синтаксис Intel: mov eax, 1 (назначение инструкции, источник)

Синтаксис AT & T: movl $1,% eax (источник инструкции, пункт назначения)

Синтаксис Intel довольно понятен. В приведенном выше примере количество перемещаемых данных выводится из размера регистра (32 бита в случае eax). Используемый режим адресации выводится из самих операндов.

Есть некоторые причуды, когда дело доходит до синтаксиса AT & T. Во-первых, обратите внимание на суффикс l в конце инструкции mov, это означает long и означает 32 бита данных. Другие суффиксы инструкций включают w для слова (16 бит - не), которое должно быть путано с размером слова вашего CPU!), q для четырехзначного (64 бит) и b для одного байта. Хотя это не всегда требуется, обычно вы увидите код сборки, который использует синтаксис AT & T, явно указывая количество данных, которыми управляет команда.

В режиме адресации, используемом в исходном и целевом операнде, требуется дополнительная разъяснительная информация. $ означает immediate адресацию, так как используется значение самой инструкции. В приведенном выше примере, если он был написан без этой $, будет использоваться адресация direct, т.е. ЦП будет пытаться извлечь значение по адресу памяти 1 (что, скорее всего, приведет к ошибке сегментации). % означает register адресацию, если вы не указали это в приведенном выше примере eax, будет рассматриваться как symbol, то есть адрес помеченной памяти, что более чем вероятно приведет к undefined reference в время ссылки. Поэтому обязательный явный для режима адресации, используемого и операндом источника и получателя.

Описанные операнды памяти также различаются:

Intel: [базовый регистр + индекс * размер индекса + смещение]

AT & T: смещение (базовый регистр, индекс, размер индекса)

Синтаксис Intel упрощает определение того, что происходит, чтобы найти адрес памяти. С синтаксисом AT & T результат будет таким же, но вы должны знать, что происходит вычисление.

должен, теоретически, по крайней мере, производить один и тот же двоичный

Это полностью зависит от вашей инструментальной цепочки.

Каковы причины того, чтобы поддержать тот или иной?

Индивидуальное предпочтение, конечно, по моему мнению, сводится к тому, какой синтаксис вам будет более комфортным при обращении к памяти. Вы предпочитаете принудительное объяснение синтаксиса AT & T? Или вы предпочитаете, чтобы ваш ассемблер выяснял эту минимальную мелочь для вас?

Это параметры командной строки? Макросы? Немагнитные ключевые слова?

Это связано с самим ассемблером (GAS, NASM). Опять же, личные предпочтения.

Ответ 2

NASM фактически использует собственный вариант синтаксиса Intel, отличный от синтаксиса MASM, используемого в официальной документации Intel. Имена опкодов и порядки операнда такие же, как в Intel, поэтому инструкции выглядят одинаково на первый взгляд, но любая значительная программа будет иметь различия. Например, с помощью MASM команда, используемая MOV ax, foo, зависит от типа foo, в то время как NASM не имеет типов, и это всегда собирается для немедленной инструкции перемещения. Когда размер операнда не может быть определен неявно, MASM требует использования DWORD PTR, где NASM использует DWORD для обозначения того же самого. Большая часть синтаксиса за пределами командной мнемоники и базового формата и порядка операндов отличается.

С точки зрения функциональности NASM и GAS практически одинаковы. Оба имеют ассемблерные макрообъекты, хотя NASM более обширна и более зрелая. Многие файлы исходного кода GAS используют препроцессор C вместо собственной поддержки макросов GAS.

Это самое большое различие между двумя сборщиками - это поддержка 16-битного кода. У GAS нет поддержки для определения сегментов x86. С GAS вы ограничены созданием простых односегментных 16-битных двоичных изображений, в основном только загрузочных секторов и .COM файлов. NASM имеет полную поддержку сегментов и поддерживает объектные файлы формата OMF, которые вы можете использовать с подходящим компоновщиком для создания сегментированных 16-разрядных исполняемых файлов.

В дополнение к формату объектного файла OMF, NASM поддерживает несколько форматов, которые GAS нет. GAS обычно поддерживает только собственный формат для работы машины, в основном ELF, PE-COFF или MACH-O. Если вы хотите поддерживать другой формат, вам нужно построить "кросс-компиляционную" версию GAS для этого формата.

Еще одна заметная разница заключается в том, что GAS поддерживает создание DWARF и 64-разрядной информации разворота Windows (более поздняя, ​​требуемая для Windows x64 ABI), в то время как с созданным NASM созданием разделов и заполнением самих данных.