C++ 内联程序集分支目标超出范围
我不熟悉组装。最近,我需要Visual Studio 2013中的内联程序集来提高性能 但我来谈谈分支目标范围问题:C++ 内联程序集分支目标超出范围,c++,assembly,x86,inline-assembly,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 =
_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*/
}
}
for(int i=0;i
这似乎奏效了
但我不知道这个方法是否足够好
有没有什么好方法可以在不引起分支范围问题的情况下处理循环部分?您看到的原因是
loop
和jecxz
†都是短跳转指令。您使用的C循环没有使用循环
;它使用jcc
进行分支(包括短形式和近形式)
如果需要,您仍然可以使用完全组装。您不能使用循环
:
mov ecx, cnt
jmp ATEST
AL1:
/* fun happens here */
ATEST:
dec ecx
jns AL1
用技术术语来说:
- 短跳转使用有符号的1字节偏移量(从下一条指令开始),它提供了[-128128]的范围(正如您已经计算出的)
- 近跳转使用有符号的2字节(在16位模式下)或4字节(在32位和64位模式下)偏移量,分别提供[-32768、32768]和[-2147483648、2147483648]的范围。
- 在16位和32位模式下,这意味着近跳转可以访问当前代码段中的任何位置
jecxz
从技术上讲不是jcc
指令;它不在jcc
操作码范围内,不检查标志,也没有相应的cmovcc
或setcc
表单
——为了完整性,
jmp
(但不包括jcc
)还支持近间接跳转、远跳转和远间接跳转。您看到的原因是loop
和jecxz
†都是短跳转指令。您使用的C循环不使用loop
;它使用jcc
进行分支(具有短跳转和近跳转形式)
如果需要,您仍然可以使用完整汇编。您只是不能使用循环
:
mov ecx, cnt
jmp ATEST
AL1:
/* fun happens here */
ATEST:
dec ecx
jns AL1
用技术术语来说:
- 短跳转使用有符号的1字节偏移量(从下一条指令开始),它提供了[-128128]的范围(正如您已经计算出的)
- 近跳转使用有符号的2字节(在16位模式下)或4字节(在32位和64位模式下)偏移量,分别提供[-32768、32768]和[-2147483648、2147483648]的范围。
- 在16位和32位模式下,这意味着近跳可以访问当前代码段中的任何位置
jecxz
从技术上讲不是jcc
指令;它不在jcc
操作码范围内,不检查标志,也没有相应的cmovcc
或setcc
表单
‡为了完整起见,
jmp
(但不是jcc
)也支持近间接跳转、远跳转和远间接跳转。jecxz
也有一个短操作数。@gsg从技术上讲jecxz
不是jcc
指令(它不在jcc
指令的操作码范围内,它不查看标志,也没有setcc
表单),但由于某种原因,它列在《英特尔手册》的jcc
部分,我将更新我的答案以解决这个问题。谢谢!jecxz
也有一个短操作数。@gsg从技术上讲jecxz
不是jcc
指令(它不在jcc
指令的操作码范围内,它不看标志,也没有setcc
表单),但由于某种原因,它被列在英特尔手册的jcc
部分,我将更新我的答案以解决这个问题。谢谢!