2015-01-17 36 views
0

我是新裝配。最近我需要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*/ 
    } 
} 

這似乎是工作。

但我不知道這種方法是否夠好?

是否有任何好的方法來處理循環部分而不會導致分支範圍問題?

回答

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)也支持接近間接跳轉,遠跳轉和遠間接跳轉。

+1

'jecxz'也有一個簡短的操作數。 – gsg

+0

@gsg技術上'jecxz'不是'jcc'指令(它不在''jcc'指令的操作碼範圍之外,它沒有看標誌,也沒有'setcc'形式),但是因爲由於某些原因,它已列在英特爾手冊的'jcc'部分,我會更新我的答案以解決該問題。謝謝! –