【问题标题】:Assembler - Load value from register instead of Immediate value汇编器 - 从寄存器加载值而不是立即值
【发布时间】:2014-04-29 06:59:57
【问题描述】:

一些 AMD64/x86 命令需要立即数作为操作数(例如 imm8)。是否可以使用存储在某个寄存器中的值(例如 ah)而不是这个硬编码值?

例如:

如果我想移动一个 xmm 寄存器,有 pslldq-command:

PSLLDQ xmm1, imm8

我必须将它移动 n 次(其中 n 存储在寄存器中)。不带条件跳转可以吗?

【问题讨论】:

  • 您确定没有任何形式的此命令将寄存器(可能是通用寄存器)作为第二个参数吗?

标签: assembly x86-64 cpu-registers


【解决方案1】:

您可以使用 pshufb 和查找表来模拟它。

shl eax, 4
pshufb xmm0, [lut + eax]

查找表将以(我认为)开头

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
80 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
80 80 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D

您也可以使用普通的旧未对齐读取,并且不使用任何“奇怪”的内容:(未测试)

movdqa [temp + 16], xmm0
pxor xmm0, xmm0
movdqa [temp], xmm0
neg eax
movdqu xmm0, [eax + temp + 16]

但这可能会受到存储转发失败的影响,这可能会花费十几个周期。

【讨论】:

    【解决方案2】:

    如果代码段的长度相等,您可以使用跳转表或索引分支进入重复的代码段。

    【讨论】:

      【解决方案3】:

      x86 下没有这样的指令(目前)。 但你可以用硬核方式做:

          mov     cl, n                        ;n as shift count number from 0 to 31
          mov     byte ptr[@_PSLLDQ + 4], cl   ;overwrite last byte of instruction
          mfence                               ;ensure that intruction is globally visible 
      @_PSLLDQ:
          PSLLDQ  xmm1, 0
      

      当然,您的代码存储器必须启用写入访问权限。

      【讨论】:

      • 这可能会立即崩溃;什么明智的操作系统使代码部分可写?即使是,流水线。当 PSLLDQ 指令被覆盖时,它已被 CPU 长时间提取并等待执行。模数,数据和代码缓存是不同的;如果在覆盖之前加载了带有 PSLLDQ 的代码缓存行,CPU 将看不到覆盖。模数,乱序执行。简而言之,不要。
      • @Seva Alekseyev:你可能是对的,所以我添加了MFENCE instuction。
      猜你喜欢
      • 2015-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      • 2019-12-26
      相关资源
      最近更新 更多