【问题标题】:Inline assembly branch target is out of range内联汇编分支目标超出范围
【发布时间】:2015-01-17 07:34:12
【问题描述】:

我是组装新手。最近我需要 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*/
    }
}

这似乎行得通。

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

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

【问题讨论】:

    标签: c++ assembly x86 inline-assembly


    【解决方案1】:

    您看到的原因是 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) 的范围(正如您已经弄清楚的那样)。
    • Near 跳转使用带符号的 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>)还支持近间接跳转、远跳转和远间接跳转。

    【讨论】:

    • jecxz 也有一个短操作数。
    • @gsg 从技术上讲,jecxz 不是jcc 指令(它超出了jcc 指令的操作码范围,它不查看标志,也没有@ 987654338@ 表格),但由于某种原因它列在英特尔手册的jcc 部分,我将更新我的答案来解决这个问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-10
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多