What is the ".s" suffix in x86 instructions?

assembly, att, x86, x86-64

Solution

To understand what the `.s` suffix means, you need to understand how x86 instructions are encoded. If we take `adc` as an example, there are four main forms that the operands can take:

- The source operand is an immediate, and the destination operand is the accumulator register.

- The source operand is an immediate, and the destination operand is a register or memory location

- The source operand is a register, and the destination operand is a register or memory location.

- The source operand is a register or memory location, and the destination operand is a register.

And of course there are variants of these for the different operand sizes: 8-bit, 16-bit, 32-bit, etc.

When one of your operands is a register and the other is a memory location, it is obvious which of forms 3 and 4 the assembler should use, but when both operands are registers, either form is applicable. The `.s` prefix tells the assembler which form to use (or in the case of a disassembly, shows you which form has been used).

Looking at the specific example of `adcb %bl,%dh`, the two ways it can be encoded are as follows:

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

The first byte determines the form of the instruction used, which I'll get back to later. The second byte is what is know as a ModR/M byte and specifies the addressing mode and register operands that are used. The ModR/M byte can be split into three fields: Mod (the most significant 2 bits), REG (the next 3) and R/M (the last 3).

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

The Mod and R/M fields together determine the effective address of the memory location if one of the operands is a memory location, but when that operand is just a register, the Mod field is set to 11, and R/M is the value of the register. The REG field obviously just represents the other register.

So in the `de` byte, the R/M field holds the `dh` register, and the REG fields holds the `bl` register. And in the `f3` byte, the R/M field holds the `bl` register, and the REG fields holds the `dh` register. (8-bit registers are encoded as the numbers 0 to 7 in the order al,cl,dl,bl,ah,ch,dh,bh)

Getting back to the first byte, the `10` tells us to use the form 3 encoding, where the source operand is always a register (i.e. it comes from the REG field), and the destination operand is a memory location or register (i.e. it is determined by the Mod and R/M fields). The `12` tells us to use the form 4 encoding, where the operands are the other way around - the source operand is determined by the Mod and R/M fields and the destination operand comes from the REG field.

So the the position the registers are stored in the ModR/M byte are swapped, and the first byte of the instruction tells us which operand is stored where.

Problem

When I disassemble the `.text` sections of some binaries using `objdump` (with both AT&T and Intel syntaxes), I sometimes see instructions with a `.s` suffix, for example: `cmpb.s %bh,%ch`, `sbbl.s %edi,%edi`, or `adcb.s %bl,%dh`. Does the `.s` suffix have a valid/useful meaning (perhaps not even as a suffix), or is this an artefact of disassembling some data / padding as if it was a sequence of instructions? Thank you.

Original source

Related problems