【问题标题】:What is the ".s" suffix in x86 instructions?x86 指令中的“.s”后缀是什么?
【发布时间】:2013-05-20 18:15:10
【问题描述】:

当我使用objdump(AT&T 和英特尔语法)反汇编某些二进制文件的.text 部分时,有时会看到带有.s 后缀的指令,例如:cmpb.s %bh,%chsbbl.s %edi,%ediadcb.s %bl,%dh.

.s 后缀是否具有有效/有用的含义(甚至可能不是后缀),或者这是反汇编某些数据/填充的人工制品,就好像它是一系列指令一样?谢谢。

【问题讨论】:

标签: assembly x86 x86-64 att


【解决方案1】:

要了解.s 后缀的含义,您需要了解x86 指令的编码方式。如果我们以adc 为例,操作数可以采取的主要形式有四种:

  1. 源操作数是立即数,目标操作数是累加器寄存器。
  2. 源操作数是立即数,目标操作数是寄存器或内存位置
  3. 源操作数是寄存器,目标操作数是寄存器或内存位置。
  4. 源操作数是寄存器或内存位置,目标操作数是寄存器。

当然还有针对不同操作数大小的变体: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 告诉我们使用 form 4 编码,其中操作数是相反的——源操作数由 Mod 和 R/M 字段确定,目标操作数来自 REG 字段。

所以寄存器存储在ModR/M字节中的位置被交换,指令的第一个字节告诉我们哪个操作数存储在哪里。

【讨论】:

  • 很好的答案,我只是想补充一点,.s 后缀是 GAS 约定。没有其他汇编器使用它(但我认为它们中的任何一个实际上都不支持选择编码)。这是another page 用更多示例描述问题。
  • 有趣的阅读 - 感谢您的参考。至于其他支持多种编码的汇编器,我确信我之前在另一个汇编器(或可能是反汇编器)中遇到过类似的功能,我只是不记得语法在哪里或是什么。可能只是我自己写的。
  • GAS 具有用于编码覆盖的新语法,例如带有 r/m 源的编码的 {load} 前缀。 sourceware.org/binutils/docs/as/i386_002dMnemonics.html.
  • 相关:x86 XOR opcode differences 几乎是重复的,其答案侧重于不同方面。
【解决方案2】:

.s 指令后缀交换指令编码 (reference) 中的寄存器操作数。

【讨论】:

  • 希望有一天 SO 帖子能揭示这些人滥用什么消遣性毒品。
  • 感谢您的精彩参考。我实际上已经访问了那个网站,但是在查找各种前缀时。在看到您的链接时,我意识到我未能在那个网站(关于 binutils)和它对我的帮助之间建立联系!
猜你喜欢
  • 2016-05-24
  • 2018-05-20
  • 2019-06-20
  • 1970-01-01
  • 2012-10-05
  • 1970-01-01
相关资源
最近更新 更多