Ответ 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, меняются местами, а первый байт команды сообщает нам, какой операнд хранится где.