【问题标题】:How do you add CH to EAX in x86 assembly?如何在 x86 汇编中将 CH 添加到 EAX?
【发布时间】:2013-04-03 18:21:22
【问题描述】:

我需要在 x86 程序集中将CH 的内容添加到EAX,但似乎没有地址模式支持这一点。理想情况下,我想要一种寻址模式,例如:

ADD EAX,r8

ADD r32,r8

ADD r/m32,r8

但是ADD 没有这些模式。我无法屏蔽ECX,因为其中包含我在其他地方使用的其他垃圾,并且我已经用完了所有其他寄存器,所以我唯一的选择似乎是使用内存访问。有什么想法可以解决这个问题吗?

注意我不能使用像r/m8,r8 这样的模式,因为那样就没有进位了。

【问题讨论】:

  • 是时候使用 x64 并获得那些额外的寄存器了。 :)
  • Omitting frame pointer 帮助您释放更多寄存器,使函数调用更快,并生成更小的代码,以换取更困难的调试。但无论如何,使用 64 位更好

标签: assembly x86 cpu-registers


【解决方案1】:

正如您所观察到的,x86 只是没有如此灵活的寻址模式。您不能在一个步骤中将 8 位寄存器添加到 32 位寄存器。您的选择是释放一个寄存器和零/符号扩展然后添加 r32,r32,或者添加 r8,r8 然后在进位标志上分支以调整结果。

我建议您应该将寄存器溢出到内存中,在现代处理器上,一对内存访问比分支便宜得多(因为它将从存储缓冲区加载),您可能可以改写其他代码泄漏。

【讨论】:

    【解决方案2】:

    使用 r/m8,r8 之类的模式,并在必要时通过向 EAX 添加常量 0x100 来传播进位。

    【讨论】:

      【解决方案3】:

      如果你溢出一个寄存器,你可以避免分支。例如,

      subl $4, %esp
      

      使用指令序列:

      movl %eax, (%esp)
      ...
      movzbl %ch, %eax
      ...
      addl (%esp), %eax
      

      并在最后恢复堆栈指针:

      addl $4, %esp
      

      如果有问题,它可能会对调试此块中的代码的任何尝试造成严重破坏。


      或者,按照 Doug Currie 的建议:

      addb %ch, %al
      jnc  done
      addl 0x100, %eax
      done:
      

      【讨论】:

      • 上面的代码是不是和"push eax"一样(后面是"pop eax")?
      • 是的 - 但我不知道这是否需要在循环中,所以我想我会明确说明。
      【解决方案4】:

      改写道格的答案(英特尔语法):

        add al, ch
        jnc no_carry
        add eax, 100h
      no_carry:
      

      【讨论】:

        【解决方案5】:

        很简单,对于eax:

        add al,ch
        adc ah,0
        rorx eax,16
        adc ax,0
        rorx eax,16
        

        在第一条指令中,您添加低位并保留进位标志,在第二条指令中,您将进位标志添加到寄存器的高位。它还保留了源的内容。但请注意寄存器停止,并将代码与其他指令混合以避免它。
        补充:

        add al,ch
        adc ah,0
        bswap eax
        xchg al,ah
        adc ax
        xchg al,ah
        bswap eax
        

        【讨论】:

        • 仅适用于 haspwell(宏用于无进位版本的短旋转,需要 1 个周期)...其他选项是 bswap、xchg
        • 间接跳转可能比更多指令有更大的惩罚,所以使用更多指令是有意义的
        【解决方案6】:

        您还可以添加 32 位值并撤消添加 24 msb:s:

         add eax, ecx
         xor cl,cl           // also `and ecx, 0xffffff00` is possible
         sub eax, ecx
        

        这自然会破坏要添加的值,但会保留垃圾。 (并且重新阅读问题,实际上需要用xchg cl,ch 包围代码块,这使得解决方案对任务来说不是最佳的。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-10
          • 1970-01-01
          • 2011-04-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多