【问题标题】:add 16 bits to 64 bits register [duplicate]将16位添加到64位寄存器[重复]
【发布时间】:2018-03-07 13:18:41
【问题描述】:

这是我想做的:

   add     rsi, word [rsi+16]

我想读取 rsi+16 地址的无符号短值。我想将此值添加到 rsi。

这是我在 nasm 中遇到的错误:

s2.asm:62: error: mismatch in operand sizes

这很奇怪。为什么 nasm 和我的 cpu 无法将 16 位添加到 64 位寄存器?

这是我所做的工作:

   mov     rbx,0
   mov     bx, word [rsi+16]
   add     rsi, rbx

这很奇怪,有没有最好的方法?

谢谢

【问题讨论】:

  • 指令操作数必须具有相同的大小,符号和零扩展移动指令除外。还有don't use mov reg, 0. Always use xor reg, reg
  • movzx ebx, word [rsi+16] 会将字零扩展为rbx(x86_64 中写入ebx 会自动清除rbx 的高32 位,但指令编码比@987654331 短1 个字节@)。然后add rsi,rbx ...即您的解决方法原则上是正确的,这并不奇怪,使用组合学知识来想象机器指令编码的爆炸式增长以拥有所有可能的操作数组合。类型之间的转换在代码中非常罕见(如果由了解此限制的人编写),需要额外付费。转换是最好的。
  • @TigerTV.ru 会有不正确的结果。 (OP专门要求64b添加结果)即1 + 0xFFFF 将导致为零,而不是 0x10000
  • @TigerTV.ru 是的,如果你知道你正在添加“假”64b 值,即add 的结果永远不会设置 CF,你可以使用add si,[rsi+16],但你仍然需要付费某些架构上的性能损失,当您将使用完整的rsi 时,它仅由si 部分更新,因此性能方面最好先使用一些备用寄存器将字值扩展为 64b,然后添加两个 64b寄存器(如果您将使用rsi)。或者,如果您只需要单词值,则仅使用 si
  • @fuz:该错误报告的要点是代码生成需要在标志设置之前执行xor-zeroing。 IDK 为什么这对于首先创建那个错误设计的人来说并不明显; xor-zero / test / setcc 有效,但 test / xor-zero / setcc 无效,正如 Lu'u 在他说“总是”。唯一一次你想在标志设置后使用test / setcc / movzx eax,al 或使用mov eax,0 是当寄存器压力让你在标志设置指令之后没有备用寄存器时。而movqmovl 相比是愚蠢的。

标签: assembly nasm shellcode


【解决方案1】:

指令操作数必须具有相同的大小,符号和零扩展移动指令除外。

在您的情况下,您只能通过这种方式在一条指令中将 16 位添加到 64 位寄存器 rsi

add si, word [rsi+16]

翻译成:

\x66\x03\x76\x10

因为si寄存器(大小一个字)是rsi寄存器的低位,你可以添加到si而不影响rsi的高位字节。

但它的工作原理与 64 位加法相同只有在 16 位加法结果不溢出时。例如:

假设我们有esi=0x0000FFFF,我们将si 加1。我们有esi=0x00000000。并且 CF 将被设置,因为 16 位加法的进位输出。


如果您确实需要进位来传播到 RSI 的其余部分,则零扩展到任何其他寄存器。

movzx  rax, word ptr [rsi+16]
add    rsi, rax

翻译成:

\x48\x0F\xB7\x46\x10
\x48\x01\xC6

另外Ped7g 注明:

但是您仍然会在某些架构上付出性能损失,当您将使用完整的 rsi 时,它仅由 si 部分更新,因此在性能方面最好使用一些备用寄存器将字值扩展为首先是 64b,然后添加两个 64b 寄存器(如果您将使用rsi)。

另请参阅Why doesn't GCC use partial registers?,了解在 P6 系列 CPU 上写入 SI 然后读取 RSI 可能出现的性能问题,尽管这与 shellcode 漏洞利用负载无关。

【讨论】:

  • @Peter Cordes:感谢编辑。
  • 我认为这个故事的一般寓意是“不要对预期互操作的值使用不同的类型”。打破这个规则有时是有正当理由的,即有大量的值只有 8/16/32b 范围,但处理本身必须在 64b 范围内(甚至更多)完成,然后付出转换的代价,它并没有那么大,特别是如果它被放在算法的合理位置,即将压缩值从内存直接加载到 64b 寄存器等......但尽可能对特定计算中涉及的所有值使用相同的类型。
猜你喜欢
  • 2013-05-14
  • 2013-11-29
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多