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

时间:2015-01-17 07:34:13

标签: c++ assembly x86 inline-assembly

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

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

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

我知道原因是“操作代码”的大小超过128个字节。

我的简单解决方案是:

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

这似乎有效。

但我不知道这种方法是否足够好?

有没有什么好方法可以处理循环部分而不会导致分支范围问题?

1 个答案:

答案 0 :(得分:4)

您看到所见的原因是loopjecxz 都是短跳转说明。您拥有的C循环不使用loop;它使用jcc进行分支(包括短形式和近形式)。

如果需要,您仍然可以使用完整装配。你无法使用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在技术上不是jcc指令;它在jcc操作码范围之外,不会检查标记,也没有相应的cmovccsetcc形式。

‡为了完整性,jmp(但不是jcc)也支持近距离间接跳跃,远距离跳跃和远距离间接跳跃。