2013-02-03 108 views
3

我正在研究Cortex M0 cpu,它沒有硬件劃分,所以每次我劃分一些內容時,都會使用GCC庫函數。現在我所做的最多的一個分割是256,將短路轉換爲字節。有什麼辦法可以更有效地實現(比如通過位移),比默認的GCC庫能做到嗎?高效地將16位短轉換爲8位字符

+3

運營商'>>'會爲你做詭計嗎?你知道'8'嗎? –

+6

難道你不是指用256除?不是255? –

+2

你可能會對Hacker's delight這本書的第10章,Integer除以常量感興趣。但GCC實施者可能已經閱讀過它。假設有更好的方法之前,你有沒有看過裝配體? (注意:這個評論假定你**的**意味着255) –

回答

7

根據你的意見,你要-32768映射到0,32767映射到255因此,你想計算公式爲:

short s = /* input value */; 
unsigned char c = (unsigned char) ((s + 32768)/256); 

其他評論者所指出的,你可以做到這一點除以256右移或其他各種戰術,這是真的 - 這個合理的版本是:

unsigned char c = (unsigned char) ((s + 32768) >> 8); 

但是,不需要這種優化。 GCC是有關轉換除以恆定操作成特殊情況的實現很聰明,在這種情況下它編譯這兩種成完全相同的代碼(具有-O2 -mcpu=cortex-m0 -mthumb和GCC 4.7.2測試):

mov  r3, #128 
    lsl  r3, r3, #8 
    add  r0, r0, r3 
    lsr  r0, r0, #8 
    uxtb r0, r0 

如果你試圖太聰明(如同其他答案中的聯合或指針示例一樣),你可能會混淆它,並使事情變得更糟 - 特別是因爲那些工作是通過內存加載的,並且添加32768意味着你已經擁有了寄存器中的值。

+1

你一定會感到驚訝......我曾經看到過一個GCC端口,它通過發出乘法操作碼來處理C代碼中的顯式移位操作 - 有人可能假定了一個硬件乘法器,因此等價於成本,儘管它嘗試的實際實驗硬件運行沒有執行的乘法指令。幸運的是,作爲一個FPGA,很容易添加。希望分案的情況能夠得到更好的處理。 –

+0

@ChrisStratton:是的 - 這就是爲什麼每隔一段時間閱讀一次生成的程序集很有用,只是爲了確保你的想法正在發生實際上正在發生!雖然你描述的情況很明顯是GCC中的一個錯誤。 –

2

只是投了一個指針。

unsigned char *bytes = (unsigned char*)&yourvalue; 

現在,bytes[0]會捏捏你的價值的一個字節,並bytes[1]將舉行日等。 順序取決於你的系統的字節序

+0

請問downvoter請詳細說明一下嗎? –

+1

@JanDvorak是的,但答案**指出**結果取決於字節順序。所以它絕不是不正確的。另外,OP知道他正在開發哪種架構,所以他事先知道排序。 –

+1

當獨立於平臺的代碼更乾淨並且可能更快時,編寫平臺相關代碼幾乎沒有什麼理由 - 程序不一定將其整個生命週期花在它們最初編寫的目標上。在移位情況下,變量可能被優化編譯器保存在寄存器(而不是內存)中的可能性相當高;在指針情況下,可能會有一些優化編譯器足夠聰明地發現這是您使用指針並使用寄存器實現的唯一原因,但似乎不太可能。 –

1

你可以使用union這樣:

#include <stdio.h> 

union Word { 
    struct { 
     unsigned char high; 
     unsigned char low; 
    } byte; 
    unsigned short word; 
}; 

int main(int argc, char **argv) { 

    union Word word; 
    word.word = 0x1122; 

    printf("L = 0x%x, H = 0x%x", word.byte.low, word.byte.high); 

    return 0; 
} 
+1

使用union和bit-shifting會有性能提升嗎?看起來工會會更快,因爲沒有必要的額外操作,但也許還有其他開銷? – Muis

+0

@Joshua在彙編級別,使用'union'只有'mov'指令。 – 2013-02-03 17:20:45

+2

**這會給出錯誤的答案**,因爲它假設一個Big-Endian處理器,但是所討論的目標實際上是Little-Endian。你可以修復它,但仍然存在錯誤的風險,特別是如果代碼被移植到別的地方。 –