12
votes

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.

2
Note that .s encoding-override suffixes have been replaced by {load} and {store} prefixes, and also {vex3}, {disp32} and others. e.g. {load}add %eax, %ecx.Peter Cordes

2 Answers

14
votes

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:

  1. The source operand is an immediate, and the destination operand is the accumulator register.
  2. The source operand is an immediate, and the destination operand is a register or memory location
  3. The source operand is a register, and the destination operand is a register or memory location.
  4. 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.

8
votes

The .s instruction suffix swaps the register operands in the instruction encoding (reference).