编译器: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]逻辑地址进行寻址。
答案 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
。这样,如果优化编译器确定不需要输出,它将删除整个块。