【问题标题】:What do the assembly instructions 'seta' and 'setb' do after repz cmpsb?汇编指令“seta”和“setb”在 repz cmpsb 之后做什么?
【发布时间】:2017-06-19 12:11:51
【问题描述】:

我无法理解以下汇编行的作用:

0x401810:    repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi]
0x401812:    seta   dl
0x401815:    setb   al

我了解调试后,第一条指令逐字节比较寄存器rsirdi中的字节。

然后根据该指令设置rdxrax的低字节。

我的困惑是,当我在网上查找这条指令时,它说seta 如果它高于某个值,则将低字节设置为 0x01,否则设置为 0x00。与 setb 类似,如果字节低于某个值,则将字节设置为 0x01。

我的问题是什么值,和上面的指令有什么关系?

【问题讨论】:

  • setCC 咨询标志位,它不关心它们是如何设置的。 cmps 设置标志位。这就是联系。

标签: assembly x86 x86-64


【解决方案1】:

cmps instruction 比较 [rsi][rdi]repz prefix(也可以拼写为repe)表示递增rsirdi,然后重复cmps,只要[rsi][rdi] 比较相等。每次迭代都会设置rflags 寄存器; [rsi][rdi] 的最终迭代将由 seta(如上设置)和 setb(如下设置)使用。

换句话说,这 3 条指令的 C 伪代码如下所示:

// Initial values
uint8_t *rsi = (...);
uint8_t *rdi = (...);
uint64_t rcx = (...);

// repz cmps BYTE PTR [rsi], BYTE PTR [rdi]
while (*rsi == *rdi && rcx > 0) {
    rsi++;
    rdi++;
    rcx--;
}

uint8_t dl = *rsi > *rdi;   // seta dl
uint8_t al = *rsi < *rdi;   // setb al

请参阅文档以了解所有 setCC 说明 here

【讨论】:

  • 那么setasetb 是从哪里来的呢?
  • @Varun lyer 在最后两行。
  • 所以你在设置dlal时比较指针?不是寄存器本身的值?
  • * 是取消引用运算符@varun。他在比较寄存器的值。
  • @VarunIyer 寄存器中的值是指针(在 asm 中),比较值是内存中的值(由指针/寄存器指向)。 (只是为了澄清措辞,看起来您理解正确,即C *rsi == asm [rsi])。而setCC 确实使用rflag 作为条件检查的来源,因此C 代码正在解释功能,而不是显示ASM 变体的内部工作细节,而是再次进行两次比较。
【解决方案2】:

指令助记符为:

  • repz cmps ds:[esi], es:[edi]
    在字符串比较相等时比较字符串
  • seta dl
    如果设置了上述标志,则将dl 设置为 1,否则将 dl 设置为 0
  • setb al
    如果设置了以下标志,则将 al 设置为 1,否则,将 al 设置为 0

除了检查零标志,repz 使用ecx 寄存器来指定最大重复次数。 (ecx也叫计数器寄存器。)

[EDIT] 正如下面 Jester 正确指出的那样,没有上下标志,上下是对 cpu 状态标志位操作的结果:

  • 以上:CF = 0 和 ZF = 0
  • 以下:CF = 1

【讨论】:

  • 那么上面的标志和下面的标志是eflags寄存器的一部分?
  • 标志由 cmps 操作设置/重置。
  • 阅读这些操作我会说这看起来像一个 strncmp() 或类似的操作。
  • 没有上下标志,但有进位和零,用于检测上/下。这在指令集参考中都有很好的记录,例如“高于(CF=0 和 ZF=0)。”
猜你喜欢
  • 2018-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
相关资源
最近更新 更多