gcc内联汇编实现memset和memcpy_asm函数

源码:

#include 
#include 
#if 0
void *memcpy_asm(void *dst, const void *src, size_t size)
{
	/*movs:把指针DS:SI所指向的数据传送给指针ES:DI所指向的内存单元*/
	asm volatile(
		"shr $2, %2\n\t"
		"cld\n\t"
		"rep; movsl\n\t"
		"mov %3, %%ecx\n\t"
		"and $3, %%ecx\n\t"
		"rep; movsb\n\t"
		/*输出参数*/
		:
		/*输入参数:DS段(S:ESI) ES段(D:EDI) c:ecx m:内存变量*/
		:"D"(dst),"S"(src),"c"(size), "m"(size)
		/*cc:使用的指令会改变CPU的条件寄存器*/
		:"memory","cc");
	return dst;
}
#endif
void *memcpy_asm(void *dst, const void *src, size_t n)
{
    int d0=0, d1=0, d2=0;
    asm volatile(
        "shr $2, %0        \n\t"
        "rep ; movsl    \n\t"
        "movl %4,%%ecx    \n\t"
        "andl $3,%%ecx    \n\t"
        "jz 1f            \n\t"
        "rep ; movsb    \n\t"
        "1:"
        /*分别表示第零个操作数(%0)–到第二个(%2)操作数*/
        : "=&c"(d0),"=&D"(d1),"=&S"(d2)
        /*分别表示第三个操作数(%3)到第六个操作数(%6);其中%3个=第%0个;%5==%1;%6==%2*/
        : "0"(n),"g"(n),"1"((long)dst),"2"((long)src) 
        :"memory");
    return dst;
}


void *memset_asm(void *dst, char c, size_t size)
{
	asm volatile(
		"cld\n\t"
		"rep; stosb\n\t"
		::"a"(c),"D"(dst),"c"(size)
		:"memory","cc");
	return dst;
}

int memcmp_asm(void *dest, const void *src, size_t size)
{
	register int result = 0;
	asm volatile(
		"cld		    \n\t"
		"repe cmpsb		\n\t"
		"je  1f		    \n\t"
		"sbb %0,%0		\n\t"
		"or $1,%0    	\n\t"
		"1:"
		:"=&a"(result)       
		:"0"(result),"S"(dest),"D"(src), "c"(size), "m"(size)
		:"cc");      //clobber list 告诉gcc在这段内联汇编中哪些寄存器被显式/隐式修改
	return result;
}

int main(int argc, char *argv[])
{
	char s1[20] = {"1122334455667788"};
	char s2[20] = {"11223344AABBCCDD"};
	char str[100] = {0};
	//memset_asm(s, 'A', strlen(s));
	memcpy_asm(str, s1, strlen(s1));
	printf("s=%s str = %s\n",s1, str);
	printf("s1=s1=%d s2>s1=%d s1

gcc gccinline.c -o gccinline

执行结果:

./gccinline
s=1122334455667788 str = 1122334455667788
s1=s1=0 s2>s1=1 s1

汇编:gcc -S -O gccinline.c

cat gccinline.s
        .file   "gccinline.c"
        .text
        .globl  memcpy_asm
        .type   memcpy_asm, @function
memcpy_asm:
.LFB47:
        .cfi_startproc
        movq    %rdi, %rax
        movq    %rdx, %rcx
#APP
# 26 "gccinline.c" 1
        shr $2, %ecx        
        rep ; movsl    
        movl %rdx,%ecx    
        andl $3,%ecx    
        jz 1f            
        rep ; movsb    
        1:
# 0 "" 2
#NO_APP
        ret
        .cfi_endproc
.LFE47:
        .size   memcpy_asm, .-memcpy_asm
        .globl  memset_asm
        .type   memset_asm, @function
memset_asm:
.LFB48:
        .cfi_startproc
        movl    %esi, %eax
        movq    %rdx, %rcx
#APP
# 45 "gccinline.c" 1
        cld
        rep; stosb

# 0 "" 2
#NO_APP
        movq    %rdi, %rax
        ret
        .cfi_endproc
.LFE48:
        .size   memset_asm, .-memset_asm
        .globl  memcmp_asm
        .type   memcmp_asm, @function
memcmp_asm:
.LFB49:
        .cfi_startproc
        movq    %rdi, %r8
        movq    %rsi, %rdi
        movq    %rdx, %rcx
        movq    %rdx, -8(%rsp)
        movl    $0, %eax
        movq    %r8, %rsi
#APP
# 56 "gccinline.c" 1
        cld                 
        repe cmpsb
        je  1f              
        sbb %eax,%eax
        or $1,%eax    
        1:
# 0 "" 2
#NO_APP
        ret
        .cfi_endproc
.LFE49:
        .size   memcmp_asm, .-memcmp_asm
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "s=%s str = %s\n"
.LC1:
        .string "s1=s1=%d s2>s1=%d s1         .text
        .globl  main
        .type   main, @function
main:
.LFB50:
        .cfi_startproc
        pushq   %r12
        .cfi_def_cfa_offset 16
        .cfi_offset 12, -16
        pushq   %rbp
        .cfi_def_cfa_offset 24
        .cfi_offset 6, -24
        pushq   %rbx
        .cfi_def_cfa_offset 32
        .cfi_offset 3, -32
        subq    $176, %rsp
        .cfi_def_cfa_offset 208
        movq    %fs:40, %rax
        movq    %rax, 168(%rsp)
        xorl    %eax, %eax
        movabsq $3761687883739705649, %rax
        movq    %rax, (%rsp)
        movabsq $4051048575092012341, %rsi
        movq    %rsi, 8(%rsp)
        movl    $0, 16(%rsp)
        movq    %rax, 32(%rsp)
        movabsq $4919130649148932417, %rax
        movq    %rax, 40(%rsp)
        movl    $0, 48(%rsp)
        leaq    64(%rsp), %rdi
        movl    $12, %ecx
        movl    $0, %eax
        rep stosq
        movl    $0, (%rdi)
        movq    $-1, %rcx
        movq    %rsp, %rdi
        repnz scasb
        notq    %rcx
        leaq    -1(%rcx), %rdx
        movq    %rsp, %rsi
        leaq    64(%rsp), %rdi
        call    memcpy_asm
        leaq    64(%rsp), %rcx
        movq    %rsp, %rdx
        movl    $.LC0, %esi
        movl    $1, %edi
        movl    $0, %eax
        call    __printf_chk
        movl    $9, %edx
        leaq    32(%rsp), %rsi
        movq    %rsp, %rdi
        call    memcmp_asm
        movl    %eax, %r12d
        movl    $9, %edx
        movq    %rsp, %rsi
        leaq    32(%rsp), %rdi
        call    memcmp_asm
        movl    %eax, %ebp
        movl    $9, %edx
        movq    %rsp, %rsi
        movq    %rsp, %rdi
        call    memcmp_asm
        movl    %r12d, %r8d
        movl    %ebp, %ecx
        movl    %eax, %edx
        movl    $.LC1, %esi
        movl    $1, %edi
        movl    $0, %eax
        call    __printf_chk
        movq    168(%rsp), %rdx
        xorq    %fs:40, %rdx
        je      .L5
        call    __stack_chk_fail
.L5:
        movl    $0, %eax
        addq    $176, %rsp
        .cfi_def_cfa_offset 32
        popq    %rbx
        .cfi_def_cfa_offset 24
        popq    %rbp
        .cfi_def_cfa_offset 16
        popq    %r12
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE50:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
        .section        .note.GNU-stack,"",@progbits

你可能感兴趣的:(汇编,vim,c语言,物联网)