这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享评测,赢取加热台】ARM GCC内嵌汇编使用

共4条 1/1 1 跳转至

【分享评测,赢取加热台】ARM GCC内嵌汇编使用

工程师
2024-12-13 22:57:21   被打赏 34 分(兑奖)     打赏

简介

       上一篇(https://forum.eepw.com.cn/thread/388462/1)基于RISC-V架构的GCC内嵌汇编的验证测试,我们基于前一篇的RISC-V 的基础上按照ARM的汇编的加载、存储的代码运行在ARM 架构的芯片,内存拷贝函数只要简短的几条存储加载指令即可实现,按照RISC-V 上实现的代码逻辑,本次试验在arm cortex-m33 芯片上验证,代码实现如下:

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的。


专家
2024-12-14 05:54:46     打赏
2楼

看看


工程师
2024-12-14 13:00:49     打赏
3楼

学习了。


院士
2024-12-27 14:52:50     打赏
4楼

楼主这个和咱们使用for循环来copy比起来,速率如何啊?


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]