当我.text
使用(使用 AT&T 和 Intel 语法)反汇编某些二进制文件的部分时objdump
,有时会看到带有.s
后缀的指令,例如:cmpb.s %bh,%ch
、、sbbl.s %edi,%edi
或adcb.s %bl,%dh
。
后缀是否.s
具有有效/有用的含义(甚至可能不是后缀),或者这是反汇编某些数据/填充的人工制品,就好像它是一系列指令一样?谢谢你。
要了解.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
告诉我们使用form 3编码,其中源操作数始终是寄存器(即来自REG字段),目标操作数是内存位置或寄存器(即确定通过 Mod 和 R/M 字段)。告诉我们使用12
形式 4 编码,其中操作数是相反的——源操作数由 Mod 和 R/M 字段确定,目标操作数来自 REG 字段。
因此寄存器存储在 ModR/M 字节中的位置被交换,指令的第一个字节告诉我们哪个操作数存储在哪里。
.s
指令后缀交换指令编码中的寄存器操作数(参考)。