在重新加载'asm'时,在'CREG'类中找不到寄存器 - memcpy inline asm

时间:2012-05-03 19:21:38

标签: gcc assembly x86 inline-assembly

我正在尝试使早期版本Linux编译,您可以从git://github.com/azru0512/linux-0.12.git下载源代码。在编译''kernel / blk_drv / ramdisk.c'时,我收到了以下错误消息,

ramdisk.c:36:10: error: can't find a register in class 'CREG' while reloading 'asm'
ramdisk.c:40:10: error: can't find a register in class 'CREG' while reloading 'asm'
ramdisk.c:36:10: error: 'asm' operand has impossible constraints
ramdisk.c:40:10: error: 'asm' operand has impossible constraints

ramdisk.c中有什么,

  if (CURRENT-> cmd == WRITE) {
    (void) memcpy(addr,
            CURRENT->buffer,
            len);
  } else if (CURRENT->cmd == READ) {
    (void) memcpy(CURRENT->buffer,
            addr,
            len);
  } else
    panic("unknown ramdisk-command");

memcpy是,

extern inline void * memcpy(void * dest,const void * src, int n)
{
__asm__("cld\n\t"
  "rep\n\t"
  "movsb"
  ::"c" (n),"S" (src),"D" (dest)
  :"cx","si","di");
return dest;
}

我想这是memcpy(include / string.h)内联asm问题,所以我从它中删除了clobber列表,但没有运气。你能帮我找出出了什么问题吗?谢谢!

2 个答案:

答案 0 :(得分:3)

GCC的语法已经改变/演变了一点。

现在必须将每个特殊目标寄存器指定为输出操作数:

...("...instructions..."
   : "=c"(n), "=S"(src), "=D"(dest)

然后另外作为相同的注册为源操作数:

   : "0"(n), "1"(src), "2"(dest)

最后你需要破坏“记忆”(如果这会影响条件代码我不记得,如果是这样你也需要“cc”):

   : "memory")

接下来,因为不应移动或删除此说明,您需要使用volatile__volatile__(我不完全确定原因,但如果没有这些说明,我的测试中删除了说明 - 案例)。

最后,尝试覆盖memcpy不再是一个好主意,因为gcc“知道”如何实现该功能。您可以使用-fno-builtin覆盖gcc的知识。

这个编译(无论如何,对于我来说,在x86-64机器上有一些旧的gcc):

extern inline void * memcpy(void * dest,const void * src, int n)
{
    __asm__ volatile("cld\n\t"
        "rep\n\tmovsb\n\t"
        : "=c" (n), "=S" (src), "=D" (dest)
        : "0" (n), "1" (src), "2" (dest)
        : "memory", "cc");
    return dest;
}

答案 1 :(得分:0)

这个确切的问题&它的原因在GCC的bugzilla上进行了讨论:

Bug 43998 - inline assembler: can't set clobbering for input register

gcc不允许输入&输出寄存器作为clobbers。 如果损坏输入寄存器,请对同一寄存器执行虚拟输出:

unsigned int operation;
unsigned int dummy;
asm ("cpuid" : "=a" (dummy) : "0" ( operation) :);