Ответ 1
Множественные наборы команд многих процессоров имеют несколько способов представления функционально-идентичных инструкций. Например, исходный набор команд ARM содержит инструкции для загрузки R0 с любым значением формы b << n
, где b
- это значение от 0 до 255, а n
- четное число от 0 до 24. Если нужно загрузите R0 со значением 256, можно загрузить инструкцию, которая загружает ее с помощью 1<<8
, или можно использовать инструкцию для 4<<6
, 16<<4
или 64<<2
. Инструкции по загрузке этих разных значений имеют разные бинарные кодировки, хотя все четыре команды имеют одинаковый эффект.
Ассемблеры для некоторых компиляторов выходят из своего пути, чтобы предоставить средства для запроса какой из кажущихся одинаковых инструкций фрагмент кода должен использовать. Хотя это, как правило, не важно, бывают моменты, когда может быть желательно избежать использования определенных значений байтов внутри куска кода, или могут быть моменты, когда изменения в определенных байтах внутри фрагмента кода должны иметь особый эффект. Например, восемь бит в вышеприведенных командах ARM используются для указания значения b
. Если код должен был перезаписать часть b
одной из приведенных выше инструкций значением 12, значение, загруженное в R0, будет зависеть от того, какая из исходных четырех команд была использована; это может быть 0x0C00, 0x0300, 0x00C0 или 0x0030.
Хотя ассемблеры для 8x86 обычно не позволяют явно различать все возможные кодировки команд, могут быть некоторые контексты, где может быть полезно указать, какие байтовые значения должны быть включены в инструкцию. Например, один подход к обработке исключений заключается в том, чтобы иметь рутинную проверку, когда возникает исключение, является ли команда на обратном адресе определенной формой NOP и, если она есть, интерпретирует ее операнд как адрес структуры данных содержащие информацию об исключении. На практике большинство языков 8х86, которые поддерживают исключения, используют другие способы их обработки, но вышеупомянутый метод будет замедлять нормальные возвраты функций на время, необходимое для извлечения и выполнения длинного NOP, но будет иметь возможность обрабатывать исключительные выходы относительно эффективно (большинство языки используют более медленный подход для обработки прерываний, чтобы избежать затрат на выполнение NOP в случае без исключения, но другие языки могли бы делать что-то по-другому).