使用内存引用的GCC内联汇编程序

使用内存引用的GCC内联汇编程序,c,gcc,assembly,x86,inline-assembly,C,Gcc,Assembly,X86,Inline Assembly,我试图编写一条内联汇编指令,通过使用指向该变量的指针而不是直接引用来加载包含寄存器内容的变量 使用直接引用的代码工作正常,如下所示: 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); int x; int *y = &x

我试图编写一条内联汇编指令,通过使用指向该变量的指针而不是直接引用来加载包含寄存器内容的变量

使用直接引用的代码工作正常,如下所示:

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);
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);
灾难:

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      
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   
灾难:

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      
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   
0x000000000040052d:推送%rbp
0x000000000040052e:mov%rsp,%rbp
0x0000000000400531:子$0x10,%rsp
0x0000000000400535:lea-0x10(%rbp),%rax
0x0000000000400539:mov%rax,-0x8(%rbp)
0x000000000040053d:movl$0x1,-0xc(%rbp)
0x0000000000400544:mov-0xc(%rbp),%eax
0x0000000000400547:mov%edx,%eax
0x0000000000400549:mov-0x8(%rbp),%edx
0x000000000040054c:mov-0x10(%rbp),%eax
0x000000000040054f:mov%eax,%esi
0x0000000000400551:mov$0x4005f4,%edi
0x0000000000400556:mov$0x0,%eax
0x000000000040055b:callq 0x400410
0x0000000000400560:mov$0x0,%eax
0x0000000000400565:LEVEQ
0x0000000000400566:retq
每次打印一个非确定性整数(即bb524b90 15979050)。当在gdb中运行时,它每次都打印相同的整数(ffffe2f0),这不会根据z的值改变。有人知道这是什么原因吗

我从reg获得的是输出,而不是输入,请注意参数定位
“mov%0,%%edx;”:“=r”(x):

您对输入/输出术语感到困惑

输出操作数是从
asm
语句输出到编译器选择的寄存器中(对于
“=r”
情况)

当您使用
“=m”
时,编译器将使
%0
成为内存操作数

或者,如果使用了
“=a”
%0
将是
%eax
,编译器将假定C变量
x
的值现在在
%eax


在AT&T语法中,目标操作数是最后一个操作数。我想你知道这一点,但我认为你的输入/输出是反向的

我从reg获得的是输出,而不是输入,请注意参数定位
“mov%0,%%edx;”:“=r”(x):

您对输入/输出术语感到困惑

输出操作数是从
asm
语句输出到编译器选择的寄存器中(对于
“=r”
情况)

当您使用
“=m”
时,编译器将使
%0
成为内存操作数

或者,如果使用了
“=a”
%0
将是
%eax
,编译器将假定C变量
x
的值现在在
%eax



在AT&T语法中,目标操作数是最后一个操作数。我想您确实知道这一点,但我认为您的输入/输出是反向的。

mov%%edx,%0
。。。您正在将edx的(未定义)内容移动到(只读)变量%0?默认情况下,gcc使用att语法,这(通常)与intel语法相反。第一个程序集也不应该工作。如果它打印1,那一定是某种意外。在我看来,您可能没有意识到在AT&T语法中,源和目标是颠倒的。“源”是第一个操作数,“目标”是第二个操作数(英特尔语法是相反的)。确实不清楚您要做什么。您是在尝试获取EDX中的值并将其分配到内存位置还是以其他方式?@DanPesce:
volatile
无法保证内联程序集在内联程序集语句没有共同依赖项的情况下按它们在代码中出现的顺序出现。编译器很可能会按照这个顺序生成它们,但这不应该被假设。如果您想保证连续内联
asm
语句的顺序,您可以在模板中放置多条指令,类似于我对上述示例所做的操作。我用
\n\t
分隔每条指令。您也可以使用
以分离指令
\n\t
如果使用GCC的
-s
选项
mov%%edx,%0
使程序集输出更干净,因此。。。您正在将edx的(未定义)内容移动到(只读)变量%0?默认情况下,gcc使用att语法,这(通常)与intel语法相反。第一个程序集也不应该工作。如果它打印1,那一定是某种意外。在我看来,您可能没有意识到在AT&T语法中,源和目标是颠倒的。“源”是第一个操作数,“目标”是第二个操作数(英特尔语法是相反的)。确实不清楚您要做什么。您是在尝试获取EDX中的值并将其分配到内存位置还是以其他方式?@DanPesce:
volatile
无法保证内联程序集在内联程序集语句没有共同依赖项的情况下按它们在代码中出现的顺序出现。编译器很可能会按照这个顺序生成它们,但这不应该被假设。如果您想保证连续内联
asm
语句的顺序,您可以在模板中放置多条指令,类似于我对上述示例所做的操作。我用
\n\t
分隔每条指令。您也可以使用
以分离指令<代码>\n\t
如果使用GCC的
-s
选项,则会使程序集输出更干净