You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64汇编:如何用C语言__asm__实现单字memcpy功能?

没问题,我来帮你用GCC的内联汇编实现这个功能!先明确你的需求:把输入指针p指向的连续8个字节拷贝到size_t类型的返回值里,对应你给出的循环逻辑。下面我会给出两种实现方式,一种完全模拟原C循环的汇编逻辑,另一种是更高效的等价实现(毕竟原循环在编译器优化后其实就是单条指令的事)。

方法1:完全模拟原C循环的内联汇编

这个实现严格对应你写的for循环逻辑,逐字节拷贝:

size_t memcpy_one_word(const char *p) {
    size_t res;
    __asm__ volatile (
        // 初始化循环变量和指针寄存器
        "movq $0, %%rcx\n"          // 将循环计数器rcx置为0(对应i=0)
        "movq %[res_addr], %%rdx\n" // rdx指向res的起始地址(对应pRes)
        "movq %[src], %%rax\n"      // rax存储源指针p
        "loop_start:\n"
            "movb (%%rax), %%bl\n"   // 读取p指向的字节到bl寄存器
            "movb %%bl, (%%rdx)\n"   // 将bl中的字节写入pRes指向的地址
            "incq %%rax\n"           // p指针自增(p++)
            "incq %%rdx\n"           // pRes指针自增(pRes++)
            "incq %%rcx\n"           // 循环计数器i自增
            "cmpq $8, %%rcx\n"       // 比较i和8
            "jl loop_start\n"        // 如果i < 8,跳回循环开头继续执行
        : [res_addr] "=r" (res)      // 输出约束:res会被汇编代码修改,用寄存器存储
        : [src] "r" (p)              // 输入约束:源指针p作为输入,用寄存器传递
        : "rcx", "rdx", "rax", "bl", "memory" // 告诉编译器这些寄存器和内存被修改,避免优化冲突
    );
    return res;
}

方法2:更高效的等价实现

你的原C循环本质是把p指向的8个连续字节加载到一个64位变量中,在x86_64架构下可以直接用单条movq指令完成,和编译器优化后的代码一致:

size_t memcpy_one_word(const char *p) {
    size_t res;
    __asm__ volatile (
        "movq (%[src]), %[res]\n"   // 直接将p指向的8字节内存加载到res对应的寄存器
        : [res] "=r" (res)          // 输出约束:res是被赋值的变量
        : [src] "r" (p)              // 输入约束:源指针p
        : "memory"                   // 告知编译器内存被读取,防止不合理优化
    );
    return res;
}

一些关键说明

  • 这里用的是GCC风格的内联汇编语法(__asm__),volatile关键字用于防止编译器把这段汇编代码优化掉(因为它有读写内存的副作用)。
  • 代码仅适用于x86_64(64位x86)架构,其他架构(比如ARM)的汇编指令会完全不同。
  • 约束部分的"=r"表示输出变量会被写入,用寄存器存储;"r"表示输入变量用寄存器传递,编译器会自动选择合适的寄存器,不用手动硬编码(避免寄存器冲突)。

内容的提问来源于stack exchange,提问作者Leedehai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:18:05