内联汇编分支目标超出范围

Inline assembly branch target is out of range

我是装配新手。最近我需要 Visual Studio 2013 中的内联汇编来提高性能。

但是我来到分支目标范围问题:

_asm
{
    mov ecx, cnt;
    jecxz AZERO:
    AL1:
       /*Some operation codes here, but may be exceed 128 byte*/
    loop AL1;
    AZERO:
}

我知道原因是 "operation codes" 的大小超过了 128 字节。

我的简单解决方案是:

for (int i = 0; i < cnt; i++) {
    _asm
    {
       /*Some operation codes here, but may be exceed 128 byte*/
    }
}

这似乎有效。

但是不知道这个方法好不好?

以及有什么好的方法可以在不引起分支范围问题的情况下处理循环部分吗?

之所以会出现这种情况,是因为 loopjecxz 都是短跳转指令。你的 C 循环没有使用 loop;它使用 j<i>cc</i> 进行分支(有短形式和近形式)。

如果需要,您仍然可以使用完整汇编。你只是不能使用 loop:

    mov ecx, cnt
    jmp ATEST
AL1:
    /* fun happens here */
ATEST:
    dec ecx
    jns AL1

专业术语:

  • 短跳转使用带符号的 1 字节偏移量(从下一条指令开始),它提供 [-128, 128) 的范围(正如您已经知道的那样)。
  • 近跳转使用带符号的 2 字节(16 位模式)或 4 字节(32 位和 64 位模式)偏移量,其范围为 [-32768, 32768) 和 [ -2147483648、2147483648)。
    • 在16位和32位模式下,这意味着近跳转可以访问当前代码段中的任何位置。

† 请注意,jecxz 在技术上不是 j<i>cc</i> 指令;它在 j<i>cc</i> 操作码范围之外,它不检查标志,并且没有相应的 cmov<i>cc</i>set<i>cc</i>形式.

‡ 为了完整起见,jmp(但不包括 j<i>cc</i>)也支持近间接跳转、远跳转和远间接跳跃。