简体   繁体   English

内联汇编中的乘法指令错误

[英]multiplication instruction error in inline assembly

Consider following program: 考虑以下程序:

#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);
}

I know that add instruction is used for addition, sub instruction is used for subtraction & so on. 我知道add指令用于加法, sub指令用于减法等等。 But I didn't understand these lines: 但是我不明白这些行:

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

What is the exact meaning of :"=a"(foo) :"a"(foo), "b"(bar) ); :"=a"(foo) :"a"(foo), "b"(bar) );的确切含义是:"=a"(foo) :"a"(foo), "b"(bar) ); ? What it does ? 它能做什么 ? And when I try to use mul instruction here I get following error for the following program: 当我尝试在此处使用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);
}

Error: number of operands mismatch for `mul' 错误:“ mul”的操作数不匹配

So, why I am getting this error ? 那么,为什么我会收到此错误? How do I solve this error ? 我该如何解决这个错误? I've searched on google about these, but I couldn't find solution of my problem. 我已经在Google上搜索了这些内容,但找不到我的问题的解决方案。 I am using windows 10 os & processor is intel core i3. 我正在使用Windows 10 OS,处理器是Intel Core i3。

What is the exact meaning of :"=a"(foo) :"a"(foo), "b"(bar) ); :“ = a”(foo)的确切含义是:“ a”(foo),“ b”(bar));

There is a detailed description of how parameters are passed to the asm instruction here . 还有的参数是如何传递给汇编指令的详细介绍在这里 In short, this is saying that bar goes into the ebx register, foo goes into eax, and after the asm is executed, eax will contain an updated value for foo. 简而言之,就是说bar进入ebx寄存器, foo进入eax,在执行asm之后,eax将包含foo的更新值。

Error: number of operands mismatch for `mul' 错误:“ mul”的操作数不匹配

Yeah, that's not the right syntax for mul . 是的,那不是mul的正确语法。 Perhaps you should spend some time with an x86 assembler reference manual (for example, this ). 也许您应该花一些时间阅读x86汇编程序参考手册(例如this )。

I'll also add that using inline asm is usually a bad idea . 我还要补充一点,使用内联asm通常不是一个好主意


Edit: I can't fit a response to your question into a comment. 编辑:我无法在评论中加入对您问题的回答。

I'm not quite sure where to start. 我不太确定从哪里开始。 These questions seem to indicate that you don't have a very good grasp of how assembler works at all. 这些问题似乎表明您根本不了解汇编程序的工作方式。 Trying to teach you asm programming in a SO answer is not really practical. 试图通过SO答案教您asm编程不是很实际。

But I can point you in the right direction. 但我可以为您指明正确的方向。

First of all, consider this bit of asm code: 首先,请考虑以下asm代码:

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

Do you understand what that does? 你知道那是什么吗? What will be in eax when this completes? 完成后,eax将会是什么? What will be in ebx? ebx将会是什么? Now, compare that with this: 现在,将其与此:

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

By using the "a" constraint, you are asking gcc to move the value of foo into eax. 通过使用“ a”约束,您正在要求gcc将foo的值移动到eax中。 By using the "b" constraint you are asking it to move bar into ebx. 通过使用“ b”约束,您要求它将bar移至ebx。 It does this, then executes the instructions for the asm (ie add ). 它执行此操作,然后执行asm的指令(即add )。 On exit from the asm, the new value for foo will be in eax. 从asm退出时, foo的新值将在eax中。 Get it? 得到它?

Now, let's look at mul . 现在,让我们看看mul According to the docs I linked you to, we know that the syntax is mul value . 根据我链接到的文档,我们知道语法是mul value That seems weird, doesn't it? 看起来很奇怪,不是吗? How can there only be one parameter to mul ? mul只能有一个参数吗? What does it multiple the value with ? 它的值多少?

But if you keep reading, you see "Always multiplies EAX by a value." 但是,如果继续阅读,则会看到“始终将EAX乘以一个值”。 Ahh. 啊。 So the "eax" register is always implied here. 因此,此处始终暗含“ eax”寄存器。 So if you were to write mul %ebx , that would really be mean mul ebx, eax , but since it always has to be eax, there's no real point it writing it out. 因此,如果您要编写mul %ebx ,那的确意味着mul ebx, eax ,但是由于它总是必须是eax,因此将其写出毫无意义。

However, it's a little more complicated than that. 但是,要复杂得多。 ebx can hold a 32bit value number. ebx可以保存一个32位的数值。 Since we are using ints (instead of unsigned ints), that means that ebx could have a number as big as 2,147,483,647. 由于我们使用的是整数(而不是无符号整数),因此这意味着ebx的数字可能高达2,147,483,647。 But wait, what happens if you multiply 2,147,483,647 * 10? 但是,等等,如果乘以2,147,483,647 * 10,会发生什么? Well, since 2,147,483,647 is already as big a number as you can store in a register, the result is much too big to fit into eax. 好吧,由于2,147,483,647已经是您可以存储在寄存器中的数字,因此结果太大而无法容纳eax。 So the multiplication (always) uses 2 registers to output the result from mul . 因此,乘法(始终)使用2个寄存器从mul输出结果。 This is what that link meant when it referred "stores the result in EDX:EAX." 这就是链接所指的“将结果存储在EDX:EAX中”的含义。

So, you could write your multiplication like this: 因此,您可以这样编写乘法:

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

As before, this puts bar in ebx and foo in eax, then executes the multiplication instruction. 如前所述,这会将bar放在ebx中,并将foo放在eax中,然后执行乘法指令。

And after the asm is done, eax will contain the lower part of the result and edx will contain the upper. 在完成asm之后,eax将包含结果的下部,而edx将包含结果的下部。 If foo * bar < 2,147,483,647, then foo will contain the result you need and upper will be zero. 如果foo * bar <2,147,483,647,则foo将包含您需要的结果,并且upper将为零。 Otherwise, things get more complicated. 否则,事情会变得更加复杂。

But that's as far as I'm willing to go. 但这是我愿意去的。 Other than that, take an asm class. 除此之外,参加ASM课程。 Read a book. 读一本书。

PS You might also look at this answer and the 3 comments that follow that show why even your "add" example is "wrong." 附注:您可能还会看到答案以及随后的3条注释,这些注释说明了为什么即使您的“添加”示例也是“错误的”。

PPS If this answer has resolved your question, don't forget to click the check mark next to it so I get my karma points. PPS如果此答案解决了您的问题,请不要忘记单击其旁边的复选标记,以便获得我的业障积分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM