【问题标题】:C inline assembly memory copyC 内联汇编内存拷贝
【发布时间】:2009-11-01 00:18:17
【问题描述】:

我正在尝试将一些内联汇编写入C。我有两个数组作为输入,我需要将array1中的一个元素复制到array2中,以下是我目前拥有的:

asm (
 "movl %0,%%eax;"
 "movl %1,%%ebx;"
 "movl (%%eax),%%ecx;"
 "movl %%ecx,(%ebx);"

 "xor %%ecx,%%ecx;"
 "movl 4(%%eax),%%ecx;"
//do something on %ecx
 "movl %%ecx,4(%ebx);"  //write second
 :
 :"a"(array1),"b"(array2)
);

为什么会出现分段错误?

【问题讨论】:

  • 让解析器工作,停止添加 HTML pre 标记——你正在放弃 SO 所做的突出显示。
  • 您只是将一个元素从一个数组复制到另一个数组吗?这看起来不像是汇编优化能帮上忙的事情。
  • 你应该添加更多关于你为什么要在汇编中这样做的细节,否则你会得到很多“为什么要麻烦?”答案。
  • 你能告诉你是哪一行导致了分段错误吗?

标签: c assembly inline-assembly memcpy


【解决方案1】:

您的内联汇编代码已损坏。你不能直接使用 EAX 和 EBX 而不将它们添加到 clobber 列表中。否则编译器不知道哪些寄存器被修改了。

很可能您修改的其中一个寄存器包含该死的重要内容,后来导致分段错误。


这段代码会将array1中的一个元素复制到array2:

asm (
 "movl (%0), %%eax \n\t" /* read first dword from array1 into eax */
 "movl %%eax, (%1) \n\t" /* write dword into array2
 : /* outputs */
 : /* inputs */ "r"(array1),"r"(array2)
 : /* clobber */ "eax", "memory"
);

具有适当寄存器约束的更好版本会像这样删除硬编码的 EAX:

int dummy;
asm (
 "movl (%1), %0 \n\t"
 "movl %0, (%2) \n\t"
 : /* outputs, temps.. */ "=r" (dummy) 
 : /* inputs */           "r"(array1),"r"(array2)
 : /* clobber */          "memory"
);

顺便说一句-总的来说,我感觉您对汇编程序还不太熟悉。由于所有编译器的魔力,编写内联汇编程序有点困难。我建议你先用汇编写一些简单的函数,然后把它们放在一个单独的.S文件中。这样容易多了。。

【讨论】:

  • 谢谢,这正是我需要的。我只知道一些 MIPS32 和 MIPS64 指令,这是我第一次编写内联汇编。顺便说一句,我认为 AT&T 中的 movl 指令是 movl source,destination 所以从 array1 读取第一个 dword 到 eax 应该是 "movl (%0), %%eax \n\t" 对吗?
  • 可能是..我总是尽量避免这种 AT&T 语法.. intel 语法更简洁..
  • 是的,AT&T 语法是 source, dest - 我已经做了小修正。
  • 只是为了记录,在循环中使用其中任何一个都是正确的,但是对于性能来说完全是垃圾,特别是对于缓存中的热数据。编译器无法使用像4(%rdi) 这样的寻址模式展开,因为您的asm 约束迫使它在寄存器中实现精确的指针值(Looping over arrays with inline assembly)。最重要的是,您一次只复制 4 个字节,而不是使用 XMM 或 YMM regs 复制 16 或 32 个字节!即使是rep movsd(快速字符串微码)对于除最小数组之外的任何数组都将优于一次 4 字节。
【解决方案2】:

您最好的选择是 C 代码:

target_array[target_idx] = source_array[source_idx];

只要索引受到控制,就可以避免分段错误。

【讨论】:

    【解决方案3】:

    memcpy 呢?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 2012-06-05
      • 1970-01-01
      • 2017-11-01
      • 2012-10-20
      • 2012-04-19
      • 2015-06-13
      相关资源
      最近更新 更多