x86逻辑地址语法错误

时间:2013-12-26 16:04:43

标签: c++ x86 inline-assembly

编译器:gcc 4.7.1, 32bit, ubuntu

以下是一个例子:

    int main(void)
    {
        unsigned int mem = 0;

        __asm volatile
        (
            "mov ebx, esp\n\t"
            "mov %0, [ds : ebx]\n\t"
            : "=m"(mem)
        );

        printf("mem = 0x%08x\n", mem);

        return 0;
    }

gcc -masm=intel -o app main.c

汇编程序消息:invalid use of register!

据我所知,ds和ss指向同一段。我不知道为什么我不能使用[ds:ebx]逻辑地址进行寻址。

1 个答案:

答案 0 :(得分:2)

您的代码有两个问题:

一个:间接内存引用应为:

mov %0, ds : [ebx]

也就是说,括号中的ds

两个:您正在使用内存约束(=m)来引用mem变量。这是不可能的,因为它是一个局部变量,因此没有固定的地址。此外,单个指令不能同时具有内存中的原点和目标,您必须使用寄存器。最简单的方法是指示=g基本上意味着无论,但在您的情况下,这是不可能的,因为esp无法直接移动到内存。您必须使用=r

:(?)您正在破坏ebx注册表,因此您应该声明它,否则请不要那样使用它。这不会阻止编译,但会使你的代码行为不规律。

简而言之:

  unsigned int mem = 0;
  __asm volatile
  (
    "mov ebx, esp\n\t"
    "mov %0, ds : [ebx]\n\t"
    : "=r"(mem) :: "ebx"
  );

或者最好不要强制使用ebx,而是让编译器决定:

  unsigned int mem = 0, temp;
  __asm volatile
  (
    "mov %1, esp\n\t"
    "mov %0, ds : [%1]\n\t"
    : "=r"(mem) : "r"(temp)
  );

顺便说一句,您不需要此代码中的volatile关键字。即使不需要输出,也可以避免对汇编器进行优化。如果您编写副作用的代码,请添加volatile,但如果您编写代码以获取输出,请不要添加volatile。这样,如果优化编译器确定不需要输出,它将删除整个块。