簡體   English   中英

手臂組件模具組更換

[英]arm assembly memset replacement

我是ARM裝配的新手,對我來說很光鮮。 我正在為Android編寫音樂可視化應用程序。 我正處於我想要優化的地方,所以現在我正在嘗試。 下面是我對8位memset混合ASM和C實現的嘗試。

它在某處造成了崩潰。 我無法將gdb附加到進程,因為應用程序在gdb啟動之前退出,因此我無法單步執行操作。

這看起來不錯嗎? 我從來沒有完全繞過內存對齊,但是我確實知道ARM是4字節對齊的。 我不確定這是否是對解決方案的暗示。 我認為混合方法是在一個匯編循環中堆疊大部分操作,然后每次傳遞8個字節完成它,可以解決任何對齊問題。 我在想這個是正確的嗎? 我對於出了什么問題感到困惑。 這與memcpy函數非常類似,我當時唯一的問題是clobber列表是空的。 將這些寄存器添加到clobber列表完成了該函數,我無法弄清楚這個memset函數我缺少什么。

任何提示?

* Memset functions, 1 byte memset */
static void *mem_set8_arm (void *dest, int c, visual_size_t n)
{
    uint32_t *d = dest;
    uint8_t *dc = dest;
    uint32_t setflag32 =
        (c & 0xff) |
        ((c << 8) & 0xff00) |
        ((c << 16) & 0xff0000) |
        ((c << 24) & 0xff000000);
    uint8_t setflag8 = c & 0xff;

#if defined(VISUAL_ARCH_ARM)

    while (n >= 64) {
        __asm __volatile
        (
            "\n\t mov r4, %[flag]"
            "\n\t mov r5, r4"
            "\n\t mov r6, r4"
            "\n\t mov r7, r4"
            "\n\t stmia %[dst]!,{r4-r7}"
            "\n\t stmia %[dst]!,{r4-r7}"
        :: [dst] "r" (d), [flag] "r" (&setflag32) : "r4", "r4", "r6", "r7");

        d += 16;

        n -= 64;
    }

#endif /* VISUAL_ARCH_ARM */

    while (n >= 4) {
        *d++ = setflag32;
        n -= 4;
    }

    dc = (uint8_t *) d;

    while (n--)
        *dc++ = setflag8;

    return dest;
}

有四個寄存器的stmia寫入16個字節,所以兩次寫入32個字節。 您將16添加到指向32位值的指針,每次有效地添加64,因此會有漏洞。

此外,ARM沒有32位立即數,但許多匯編程序通過在函數后面的特殊區域生成數據字段並將mov轉換為PC相對的ldr 檢查生成的匯編器輸出是否可能在指令流的中間生成該字段。

另外,您可以在匯編器中生成32位值:

mov r4, %[mask]
orr r4, r4, r4 lsl #16
orr r4, r4, r4 lsl #8

由於這是一個8位立即數,它適合,並且不需要生成ldr

當你在它時,只需將整個循環拉入匯編程序,這樣你就可以重用地址寄存器。 眾所周知,gcc不能優化包含內聯匯編程序的例程。

那是錯字嗎:

:: [dst] "r" (d), [flag] "r" (&setflag32) : "r4", "r4", "r6", "r7");

您不是在說"r4", "r5", "r6" ...嗎?

你的自制memset會比原來的memset快嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM