【发布时间】:2017-09-13 20:57:10
【问题描述】:
我正在尝试编写一个内联汇编指令,该指令将使用指向该变量的指针而不是直接引用来加载具有寄存器内容的变量。
使用直接引用的代码可以正常工作,如下所示:
int x;
int *y = &x;
int z = 1;
__asm__ __volatile__ ("mov %%edx, %0;"::"r"(z):);
__asm__ __volatile__ ("mov %0, %%edx;":"=r" (x)::);
printf("\n%x\n", x);
disasm:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub $0x10,%rsp
0x0000000000400535 <+8>: lea -0x10(%rbp),%rax
0x0000000000400539 <+12>: mov %rax,-0x8(%rbp)
0x000000000040053d <+16>: movl $0x1,-0xc(%rbp)
0x0000000000400544 <+23>: mov -0xc(%rbp),%eax
0x0000000000400547 <+26>: mov %edx,%eax
0x0000000000400549 <+28>: mov %eax,%edx
0x000000000040054b <+30>: mov %eax,-0x10(%rbp)
0x000000000040054e <+33>: mov -0x10(%rbp),%eax
0x0000000000400551 <+36>: mov %eax,%esi
0x0000000000400553 <+38>: mov $0x4005f4,%edi
0x0000000000400558 <+43>: mov $0x0,%eax
0x000000000040055d <+48>: callq 0x400410 <printf@plt>
0x0000000000400562 <+53>: mov $0x0,%eax
0x0000000000400567 <+58>: leaveq
0x0000000000400568 <+59>: retq
它按预期输出 1
指针版本如下所示:
int x;
int *y = &x;
int z = 1;
__asm__ __volatile__ ("mov %%edx, %0;"::"r"(z):);
__asm__ __volatile__ ("mov (%0), %%edx;":"+r" (y)::);
//or
__asm__ __volatile__ ("mov %[mem], %%edx":[mem] "=m" (y)::);
printf("\n%x\n", x);
disasm:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub $0x10,%rsp
0x0000000000400535 <+8>: lea -0x10(%rbp),%rax
0x0000000000400539 <+12>: mov %rax,-0x8(%rbp)
0x000000000040053d <+16>: movl $0x1,-0xc(%rbp)
0x0000000000400544 <+23>: mov -0xc(%rbp),%eax
0x0000000000400547 <+26>: mov %edx,%eax
0x0000000000400549 <+28>: mov -0x8(%rbp),%edx
0x000000000040054c <+31>: mov -0x10(%rbp),%eax
0x000000000040054f <+34>: mov %eax,%esi
0x0000000000400551 <+36>: mov $0x4005f4,%edi
0x0000000000400556 <+41>: mov $0x0,%eax
0x000000000040055b <+46>: callq 0x400410 <printf@plt>
0x0000000000400560 <+51>: mov $0x0,%eax
0x0000000000400565 <+56>: leaveq
0x0000000000400566 <+57>: retq
这每次都会打印一个不确定的整数(即 bb524b90 15979050)。在 gdb 中运行时,它每次都打印相同的整数 (ffffe2f0),它不会根据 z 的值而改变。有谁知道是什么原因造成的?
【问题讨论】:
-
mov %%edx, %0所以...您正在将 edx 的(未定义)内容移动到(只读)变量 %0?默认情况下,gcc 使用 att 语法,这(通常)与 intel 语法相反。 -
第一个程序集也不应该工作。如果打印的是 1,那一定是个意外。
-
在我看来,您几乎没有意识到在 AT&T 语法中源和目标是相反的。源是第一个操作数,目标是第二个(Intel 语法相反)
-
确实不清楚您要做什么。您是要获取 EDX 中的值并将其放入内存位置还是相反?
-
@DanPesce :
volatile不保证如果内联汇编语句没有共同的依赖关系,内联汇编将按照它们在代码中出现的顺序出现。很可能编译器会按该顺序生成它们,但不应该假设。如果您想保证连续内联asm语句的顺序,您可以在模板中放置多个指令,类似于我对上面示例所做的操作。我用\n\t分隔每条指令。您也可以使用;来分隔指令。如果您使用 GCC 的-Soption,\n\t会使程序集输出更干净
标签: c gcc assembly x86 inline-assembly