2017-02-16 70 views
0

请考虑下面的程序:乘法指令错误

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo+bar=%d\n", foo); 
} 

我知道add指令用于另外,sub指令用于减法&等。但我不明白这些行:

__asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 

什么是:"=a"(foo) :"a"(foo), "b"(bar));的确切含义是什么?它能做什么 ?当我尝试使用mul指令在这里我获得以下以下程序错误:

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("mul %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo*bar=%d\n", foo); 
} 

错误:'MUL”

那么,为什么我收到此错误的操作数不匹配的号码?我该如何解决这个错误?我在谷歌搜索这些,但我找不到解决我的问题。我使用的是Windows 10操作系统&处理器是英特尔酷睿i3。

回答

4

What is the exact meaning of :"=a"(foo) :"a"(foo), "b"(bar));

有关如何将参数传递给asm指令here的详细说明。简而言之,这表示bar进入ebx寄存器,foo进入eax,并且在执行asm后,eax将包含foo的更新值。

Error: number of operands mismatch for `mul'

是的,这不是mul的正确语法。也许你应该花一些时间用x86汇编参考手册(例如,this)。

我还补充说使用内联asm通常是bad idea


编辑:我无法对您的问题做出回应。

我不太确定从哪里开始。这些问题似乎表明,您对汇编程序的工作方式没有很好的掌握。试图在SO答案中教你ASM编程并不实际。

但我可以指出你在正确的方向。

首先,考虑此位的汇编代码:

movl $10, %eax 
movl $15, %ebx 
addl %ebx, %eax 

你明白做什么?当这个完成时,eax中会有什么? ebx中会有什么?现在,比较,与此:

int foo = 10, bar = 15; 
__asm__ __volatile__("add %%ebx,%%eax" 
        :"=a"(foo) 
        :"a"(foo), "b"(bar) 
        ); 

通过使用“一”的约束,你问的gcc来的foo值移入EAX。通过使用“b”限制,您要求它将bar转换为ebx。它执行此操作,然后执行asm的指令(即add)。退出asm后,foo的新值将在eax中。得到它?

现在,让我们看看mul。根据我与您联系的文档,我们知道语法是mul value。这似乎很奇怪,不是吗? mul只能有一个参数?它是多少值

但是,如果你继续读,你会看到“始终由值相乘EAX。”啊。所以“eax”寄存器总是隐含在这里。所以,如果你写mul %ebx,那真的会平均mul ebx, eax,但因为它总是是EAX,有它写出来没有真正的点。

但是,它比这更复杂一点。 ebx可以保存一个32位的数值。由于我们使用整数(而不是无符号整数),这意味着ebx可以有一个大到2,147,483,647的数字。但是等等,如果你乘以2,147,483,647 * 10会发生什么?那么,因为2,147,483,647已经可以存储在一个寄存器中,所以它的结果太大了,不适合eax。所以乘法(总是)使用2个寄存器来输出mul的结果。当它提到“将结果存储在EDX:EAX中”时,这就是该链接的含义。

所以,你可以写你的乘法是这样的:正如前面

int foo = 10, bar = 15; 
int upper; 
__asm__ ("mul %%ebx" 
     :"=a"(foo), "=d"(upper) 
     :"a"(foo), "b"(bar) 
     :"cc" 
     ); 

,这使酒吧EBX和Foo在EAX,然后执行乘法指令。

和ASM完成后,EAX将包含结果的下部和EDX将包含上。如果foo * bar < 2,147,483,647,那么foo将包含您需要的结果并且upper将为零。否则,事情变得更加复杂。

但是,这是因为就我愿意去。除此之外,参加一个asm课程。读一本书。

PS你也可能看this答案并遵循展会的3条评论为什么连“加入”的例子是“错误的”。

PPS如果这个答案已经解决了你的问题,不要忘记点击旁边的选中标记,所以我让我的荣誉点数。

+0

这里“a”和“b”表示什么? – Destructor

+0

如果您阅读了链接到asm的文档,您将看到引用的字符串是描述如何将C语言变量映射到asm可以理解的东西的“约束”(参见i386部分[here](https:// gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html))。 “a”是指eax寄存器。 “b”是指ebx。 –

+0

好的谢谢。我知道了。但我仍然有一个问题。我想将foo和bar变量的值与foo中的结果相乘。我已经访问了您提供的有关多次违规的链接,但是我仍然很难知道我应该怎么做才能做到这一点? – Destructor