Что такое суффикс ".s" в инструкциях x86?

Когда я разбираю разделы .text некоторых двоичных файлов с помощью objdump (с синтаксисами AT & T и Intel), иногда я вижу инструкции с суффиксом .s, например: cmpb.s %bh,%ch, sbbl.s %edi,%edi, или adcb.s %bl,%dh.

Имеет ли суффикс .s допустимый/полезный смысл (возможно, даже не как суффикс), или это артефакт для дизассемблирования некоторых данных/отступов, как если бы это была последовательность инструкций? Спасибо.

Ответ 1

Чтобы понять, что означает суффикс .s, вам нужно понять, как кодируются инструкции x86. Если взять adc в качестве примера, есть четыре основные формы, которые могут принимать операнды:

  • Исходный операнд является немедленным, а операнд назначения - это регистр аккумулятора.
  • Исходный операнд является немедленным, а операнд назначения - регистром или ячейкой памяти.
  • Исходный операнд - это регистр, а операнд назначения - регистр или ячейка памяти.
  • Исходный операнд - это регистр или ячейка памяти, а операнд назначения - регистр.

И, конечно, есть варианты для разных размеров операндов: 8-битные, 16-битные, 32-битные и т.д.

Когда один из ваших операндов является регистром, а другой - ячейкой памяти, очевидно, какой из форм 3 и 4 должен использовать ассемблер, но когда оба операнда являются регистрами, применима любая форма. Префикс .s сообщает ассемблеру, какая форма использовать (или в случае разборки, показывает вам, какая форма была использована).

Если вы посмотрите на конкретный пример adcb %bl,%dh, два способа его кодирования следующие:

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh

Первый байт определяет форму используемой инструкции, к которой я вернусь позже. Второй байт - это то, что известно как байт ModR/M и задает режим адресации и используемые операнды регистров. Байт ModR/M можно разделить на три поля: Mod (наиболее значимые 2 бита), REG (следующие 3) и R/M (последние 3).

de: Mod=11, REG = 011, R/M = 110
f3: Mod=11, REG = 110, R/M = 011

Поля Mod и R/M вместе определяют эффективный адрес ячейки памяти, если один из операндов является местом памяти, но когда этот операнд является только регистром, поле Mod установлено равным 11, а R/M - значение регистра. Поле REG, очевидно, просто представляет другой регистр.

Итак, в байте de поле R/M содержит регистр dh, а поля REG содержат регистр bl. А в байте f3 поле R/M содержит регистр bl, а поля REG содержат регистр dh. (8-битные регистры кодируются как числа от 0 до 7 в порядке al, cl, dl, bl, ah, ch, dh, bh)

Возвращаясь к первому байту, 10 говорит нам использовать кодировку формы 3, где исходный операнд всегда является регистром (т.е. он исходит из поля REG), а операнд назначения - это ячейка памяти или регистр (т.е. определяется полями Mod и R/M). В 12 указывается, что мы используем кодировку формы 4, где операнды - наоборот - исходный операнд определяется полями Mod и R/M, а операнд назначения - из поля REG.

Таким образом, позиция, в которой регистры хранятся в байте ModR/M, меняются местами, а первый байт команды сообщает нам, какой операнд хранится где.

Ответ 2

Суффикс команды .s заменяет операнды регистров в кодировке команд (ссылка).