4

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

ADD EAX,r8

或者

ADD r32,r8

或者

ADD r/m32,r8

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

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

4

6 回答 6

3

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

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

于 2013-04-03T18:31:40.627 回答
2

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

于 2013-04-03T18:24:13.907 回答
2

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

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:
于 2013-04-03T18:50:12.417 回答
1

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

  add al, ch
  jnc no_carry
  add eax, 100h
no_carry:
于 2013-04-03T21:06:44.563 回答
1

这很简单,对于 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
于 2014-10-18T11:33:58.250 回答
0

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

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

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

于 2013-04-03T20:25:31.040 回答