查看: 88|回复: 0

ARM GCC内嵌汇编使用

[复制链接]

11

主题

21

帖子

1068

积分

金牌会员

Rank: 6Rank: 6

积分
1068
发表于 2024-12-21 14:12:08 | 显示全部楼层 |阅读模式
简介
内嵌汇编代码是指在C语言中嵌入汇编代码(Inline Assembly Language in C Code),可以在对代码时间要求比较高,及在C语言中访问某些汇编指令来实现特殊功能,内嵌汇编代码主要有两种形式:基础内嵌汇编代码(basic asm):不带任何参数扩展内嵌汇编代码(extended asm):可以带输入/输出参数,一下是使用内嵌汇编实现的memcpy函数
static __attribute__((noinline)) int my_memcpy(void * src,void *  dst,int len)
{
    unsigned int tmp = 0;
    unsigned int end = (char *)src + len;

    asm volatile (
            "1: ldr %1, [%2] , #4\n"
            "str %1, [%0], #4\n"
            "cmp %2, %3 \n"
            "bcc 1b"
            : "+r" (dst), "+r" (tmp), "+r" (src)
            : "r" (end)
            : "memory");

    return len;
}
代码中添加如下测试代码,验证函数功能,对应测试代码如下:
static int cmd_mymemcpy_test(int argc, char **argv)
{

    int src[8] = {0x11111111,0x22222222,0x33333333,0x44444444,
                  0x55555555,0x66666666,0x77777777,0x88888888};
    int dst[8] = {};

    rt_kprintf("my memcpy test ret = %d\r\n",my_memcpy(src,dst,sizeof(src)));

    if(memcmp(src,dst,sizeof(src)) == 0)
        rt_kprintf("my memcpy test ok.\r\n");

    int src1[32] = {0x11111111,0x22222222,0x33333333,0x44444444,
                    0x55555555,0x66666666,0x77777777,0x88888888};
    int dst1[32] = {};

    rt_kprintf("my memcpy test ret = %d\r\n",my_memcpy(src1,dst1,sizeof(src1)));

    if(memcmp(src1,dst1,sizeof(src1)) == 0)
        rt_kprintf("my memcpy test ok.\r\n");

    return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_mymemcpy_test, mymemcpy, my memcpy test);
上述代码对应的反汇编代码如下,汇编代码主要先将函数形参压栈,然后重新分配r0-r3 寄存器内嵌汇编代码中指定的变量,按照内嵌汇编代码分配寄存器。
00005c80 <my_memcpy>:
    5c80:        b480              push        {r7}
    5c82:        b087              sub        sp, #28
    5c84:        af00              add        r7, sp, #0
    5c86:        60f8              str        r0, [r7, #12]
    5c88:        60b9              str        r1, [r7, #8]
    5c8a:        607a              str        r2, [r7, #4]
    5c8c:        2300              movs        r3, #0
    5c8e:        617b              str        r3, [r7, #20]
    5c90:        687b              ldr        r3, [r7, #4]
    5c92:        68fa              ldr        r2, [r7, #12]
    5c94:        4413              add        r3, r2
    5c96:        613b              str        r3, [r7, #16]
    5c98:        6938              ldr        r0, [r7, #16]
    5c9a:        68b9              ldr        r1, [r7, #8]
    5c9c:        697a              ldr        r2, [r7, #20]
    5c9e:        68fb              ldr        r3, [r7, #12]
    5ca0:        f853 2b04         ldr.w        r2, [r3], #4
    5ca4:        f841 2b04         str.w        r2, [r1], #4
    5ca8:        4283              cmp        r3, r0
    5caa:        d3f9              bcc.n        5ca0 <my_memcpy+0x20>
    5cac:        60b9              str        r1, [r7, #8]
    5cae:        617a              str        r2, [r7, #20]
    5cb0:        60fb              str        r3, [r7, #12]
    5cb2:        687b              ldr        r3, [r7, #4]
    5cb4:        4618              mov        r0, r3
    5cb6:        371c              adds        r7, #28
    5cb8:        46bd              mov        sp, r7
    5cba:        f85d 7b04         ldr.w        r7, [sp], #4
    5cbe:        4770              bx        lr
代码运行后运行结果也是正确的完成拷贝。
msh >mymemcpy
my memcpy test ret = 32
my memcpy test ok.
my memcpy test ret = 128
my memcpy test ok.
从上述反汇编的如下代码,对比可以看出 tmp 编译器分配r2 寄存器,dst 分配r0 寄存器,src 分配寄存器r3寄存器,end 分配r3寄存器
    5ca0:        f853 2b04         ldr.w        r2, [r3], #4
    5ca4:        f841 2b04         str.w        r2, [r1], #4
    5ca8:        4283              cmp        r3, r0
    5caa:        d3f9              bcc.n        5ca0 <my_memcpy+0x20>
   
   
    asm volatile (
            "1: ldr %1, [%2] , #4\n"
            "str %1, [%0], #4\n"
            "cmp %2, %3 \n"
            "bcc 1b"
            : "+r" (dst), "+r" (tmp), "+r" (src)
            : "r" (end)
            : "memory");
在此基础上修改代码为,修改代码为符号的方式替代%0 %1 的方式,修改代码如下:
static __attribute__((noinline)) int my_memcpy(void * src,void *  dst,int len)
{
    unsigned int tmp = 0;
    unsigned int end = (char *)src + len;

    asm volatile (
            "1: ldr %[tmp], [%[src]] , #4\n"
            "str %[tmp], [%[dst]], #4\n"
            "cmp %[src], %[end] \n"
            "bcc 1b"
            : [dst] "+r" (dst), [tmp] "+r" (tmp), [src] "+r" (src)
            : [end] "r" (end)
            : "memory");

    return len;
}
修改后生成的反汇编代码和之前也是一致的,运行测试代码也是ok的。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

用户排行榜

RA助手

主题: 116帖子:136精华:0

RA_Lance

主题: 94帖子:138精华:9

lugl

主题: 53帖子:152精华:1

xujiwei263

主题: 18帖子:87精华:0

Juggernaut

主题: 12帖子:118精华:0

books咦

主题: 11帖子:11精华:2
快速回复 返回顶部 返回列表