随笔-内联汇编

GCC 内联汇编 HOWTO https://linux.cn/article-7688-1.html
https://www.cnblogs.com/sewain/p/14707347.html

x86汇编语言基础(AT&T语法) - 玩转Linux内核的文章 - 知乎 https://zhuanlan.zhihu.com/p/627238135

    __asm__ __volatile__
    (
        "mov %1,    %%rbx\n\t"              // dest值传入rbx 
        "mov %2,    %%rcx\n\t"              // src传入rcx
        "VAGE_LOOP:\n\t"                    // 循环开始
            "mov (%%rbx),   %%r8\n\t"       // load 源地址数据到 r8
            "mov %%r8,      (%%rcx)\n\t"    // r8 store 到目标地址
            "add $8,   %%rbx\n\t"           // 源地址向后加8字节
            "add $8,   %%rcx\n\t"           // 目标地址向后加8字节
            "sub $8,   %0\n\t"              // size 减8字节
            "jne VAGE_LOOP\n\t"             // size 不为0向上跳转至循环开始处
        :"=r"(size)
        :"r"(dest),"r"(src),"0"(size)
        :"rbx","rcx","r8"
    );

使用的是AT&T语法,mov S,D,和intel汇编风格正好相反

"0"(size) 这里0是什么意思,因为size同时是输出参数,序号是从输出参数开始编号,所以size是%0,然后依次dest、src、size,size已经是输出参数了,所以用对应的输出参数作为下标
"rbx","rcx","r8" 定义被修改的寄存器,rbx、rcx 和 r8 在汇编代码中被修改,需要在输出列表中声明

+++

使用编号还是麻烦,容易出错,还有另一个更方便的操作:扩展 asm 格式还允许给这些占位符重命名,也就是给每一个寄存器起一个别名,然后在内联汇编代码中使用别名来操作寄存器。

    __asm__ __volatile__
    (
        "mov %[v1], %%rbx\n\t"              
        "mov %[v2], %%rcx\n\t"              
        "VAGE_LOOP:\n\t"                    
        "mov (%%rbx), %%r8\n\t"             
        "mov %%r8, (%%rcx)\n\t"             
        "add $8, %%rbx\n\t"                 
        "add $8, %%rcx\n\t"                 
        "sub $8, %[v3]\n\t"                 
        "jne VAGE_LOOP\n\t"                 
        : [v3]"=r"(size)                     
        : [v1]"r"(dest),[v2]"r"(src),"[v3]"(size)
        : "rbx","rcx","r8"                   
    );

"[v3]"(size) 不写或者写成 "r"(size) 都是错误的写法

posted @ 2024-09-18 23:12  LiYanbin  阅读(4)  评论(0编辑  收藏  举报