Нужно ли, чтобы каждый машинный код мог сопоставляться только с одним ассемблерным кодом?

Предположим, что эти два по существу одинаковы:

push 1

и

0x1231

Что говорит о том, что каждая инструкция по сборке сопоставляется с машинным кодом.

Но обязательно ли, чтобы каждый машинный код мог сопоставляться только с одним ассемблерным кодом?


person Mask    schedule 07.04.2010    source источник


Ответы (7)


Язык ассемблера MIPS имеет несколько «псевдоинструкций». Например, «переместить» — это внутренне просто «добавить» с неявным операндом $0.

person dan04    schedule 07.04.2010

Вы вполне могли бы определить программу на ассемблере, которая поддерживает "синонимы" для инструкций: никакого вреда не будет, если вы позволите коду пользователя FOO означать то же самое, что и BAR. Я не знаю навскидку ассемблеров, которые это делают, но вы, безусловно, можете добиться того же эффекта с помощью тривиально простого макроса в любом макроассемблере ;-).

person Alex Martelli    schedule 07.04.2010
comment
как машинный код сегмента процессора, по два слова на инструкцию? - person Mask; 07.04.2010
comment
Двоичный формат машинного кода и синтаксис языка ассемблера, который генерирует этот машинный код, совершенно не коррелированы. x86, например, имеет двоичные инструкции различной длины, от одного байта и выше, но каждая генерируется из одной инструкции языка ассемблера. - person Alex Martelli; 07.04.2010
comment
С точки зрения процессора все это последовательность битов. Как он узнает начальный и конечный биты для каждой инструкции? - person Mask; 07.04.2010
comment
@Mask, все современные процессоры используют последовательности слов (возможно, включая байты), а не биты. Те, у кого инструкции разной длины, очевидно, имеют некоторую дополнительную логику, так что, в зависимости от первого байта или слова, они знают, сколько еще им понадобится. Опять же, ассемблер (чья работа заключается в чтении текста ассемблерного кода и генерации двоичного машинного кода) не имеет к делу никакого отношения. - person Alex Martelli; 07.04.2010
comment
Да, ассемблеры действительно делают это. Почти каждый ассемблер x86 делает это для je и jz. Они означают одно и то же, но иногда программисту немного легче понять одно из двух. - person Earlz; 25.05.2011

да. Реальным примером этого является ассемблер 68k, где

Официальные мнемоники BCC (ветвь при переносе) и BCS (ветвь при переносе) можно переименовать в BHS (ветвь выше или равно) и BLO (ветвь меньше) соответственно. Многие ассемблеры 68000 поддерживают эту альтернативную мнемонику.

person David Gelhar    schedule 07.04.2010

Даже без синонимов ассемблерная инструкция может соответствовать более чем одному машинному коду.
Например. add eax, ebx можно представить как 03 C3 или 01 D8.
На самом деле это может быть полезно, например. для идентификации конкретных компиляторов.
Дополнительные примеры можно найти в этой статье.

Обратное также может быть правдой, в некотором смысле.
Пример немного надуманный, но один и тот же машинный код (F3 90) отображается либо в REP NOP, либо в PAUSE на x86.
Какой из них выполняется, зависит от процессор, на котором выполняется код.
Хотя один и тот же код операции был выбран преднамеренно и что касается состояния процессора, они не имеют значения, время выполнения и точная внутренняя реализация могут различаться в зависимости от HT (PAUSE) и ЦП без HT (NOP).

Помимо разницы между PAUSE и REP NOP, которая не имеет большого значения, можно написать машинный код, который трудно дизассемблировать статически.
Например. можно тщательно сконструировать последовательность машинного кода, которая приводит к совершенно другим инструкциям сборки, если дизассемблирование начинается, скажем, со смещения 0 по сравнению со смещением 1.
Можно также написать самомодифицирующийся код сборки, чтобы усложнить статический анализ.

person Andras Vass    schedule 07.04.2010
comment
Кстати, как машинный код сегмента процессора, по два слова на инструкцию? - person Mask; 07.04.2010
comment
@Mask: Если ваш вопрос заключается в том, есть ли в машинном коде однобайтовые инструкции, то да, их много. - person Andras Vass; 07.04.2010
comment
Нет. С точки зрения процессора все это последовательность битов. Как он узнает начальный и конечный биты для каждой инструкции? - person Mask; 07.04.2010
comment
@Mask: коды операций могут кодировать необходимую информацию об аргументах и ​​их длине. Таблица кодов операций: sandpile.org/ia32/opc_1.htm Статья об избыточности машинного кода: strchr.com/machine_code_redundancy - person Andras Vass; 07.04.2010
comment
@Mask: хотя гораздо лучшим, хотя и более длинным и сложным источником, является Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 2A: Справочник по набору инструкций, AM, в котором целая глава посвящена инструкции и формату кода операции. . intel.com/Assets/PDF/manual/253666.pdf - person Andras Vass; 07.04.2010
comment
Интересный момент: я, кажется, припоминаю, что старый ассемблер A86 использовал шаблон выбора различных синонимов машинного кода, чтобы оставить отпечаток пальца на собранном выводе. Таким образом, разработчик A86 смог узнать, кто пиратит его ассемблер... - person Brian Knoblauch; 17.08.2011
comment
@BrianKnoblauch: Стоит отметить, что некоторые производители чипов прямо запрещают использование битовых шаблонов, поведение которых было бы эквивалентно другой форме инструкций, и это часто упрощает разработку будущих чипов. Например, даже если 8088 будет считать эквивалентным mov ax,bx, закодированный как mov reg,ea, где reg=AX и ea=BX, или mov ea,reg, где ea=AX и reg=BX, требуется, -регистровые перемещения всегда используют одну конкретную форму, что освободит восемь двухбайтовых кодов операций для какой-либо другой цели. - person supercat; 07.01.2014

Я не вижу никакой концептуальной причины, по которой вы не могли бы разработать язык ассемблера, в котором более одного оператора ассемблера сопоставляются с одним и тем же кодом операции на базовом процессоре.

Я тоже не сразу вижу какой-то особенно веский повод для этого, но уже поздно и, возможно, я что-то упускаю.

person Syntactic    schedule 07.04.2010

То, что делает конкретная инструкция машинного кода, определяется процессором (или семейством процессоров), для которого она предназначена. И одна и та же инструкция машинного кода всегда будет делать одно и то же.

Обычно конкретная инструкция машинного кода дизассемблируется только до одного оператора. В некоторых более сложных наборах инструкций есть несколько способов написать одно и то же выражение на ассемблере. Хорошим примером является индексированный поиск. Некоторые операторы также могут иметь синонимы, но, опять же, для процессора они будут означать одно и то же.

Однако для архитектуры может существовать несколько целых наборов сборок. Это произошло с архитектурой x86, где есть стандартный набор, определенный Intel, и другой, основанный на стандарте, созданном AT&T, который используется GCC.

person staticsan    schedule 07.04.2010

Как правило, цель сборки состоит в том, чтобы позволить вам напрямую программировать машину без двусмысленности в отношении того, что будет выполняться. В значительной степени требуется отображение 1: 1.

Я не удивлюсь, если где-то в каком-нибудь ассемблере есть какие-то косвенные отображения, возможно, для обработки изменений кодов операций в какой-то линейке процессоров. Хотя я не знаю ни одного.

person ScottS    schedule 07.04.2010