内联汇编中的乘法指令错误
multiplication instruction error in inline assembly
考虑以下程序:
#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”的操作数数量不匹配
那么,为什么会出现此错误?我该如何解决这个错误?我在 google 上搜索过这些,但找不到解决我的问题的方法。我正在使用 windows 10 os & 处理器是 intel core i3.
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)。
我还要补充一点,使用内联汇编通常是 bad idea。
编辑:我无法将对您问题的回复放入评论中。
我不太确定从哪里开始。这些问题似乎表明您根本不了解汇编程序的工作原理。试图在 SO 答案中教你 asm 编程并不实用。
但我可以为您指明正确的方向。
首先,考虑一下这段asm代码:
movl , %eax
movl , %ebx
addl %ebx, %eax
你明白那是什么意思吗?完成后 eax 中会有什么? ebx中会有什么?现在,将其与此进行比较:
int foo = 10, bar = 15;
__asm__ __volatile__("add %%ebx,%%eax"
:"=a"(foo)
:"a"(foo), "b"(bar)
);
通过使用 "a" 约束,您要求 gcc 将 foo
的值移动到 eax 中。通过使用 "b" 约束,您要求它将 bar
移动到 ebx 中。它执行此操作,然后执行 asm 的指令(即 add
)。在退出 asm 时,foo
的新值将在 eax 中。明白了吗?
现在,让我们看看mul
。根据我 link 告诉你的文档,我们知道语法是 mul value
。这看起来很奇怪,不是吗? mul
怎么可能只有一个参数呢? 与的乘积是多少?
但是如果你继续阅读,你会看到 "Always multiplies EAX by a value." 啊。所以这里总是隐含 "eax" 寄存器。所以如果你要写 mul %ebx
,那实际上是 mul ebx, eax
,但是因为它总是 has 是 eax,所以写出来没有实际意义.
然而,它比那要复杂一点。 ebx 可以保存一个 32 位值的数字。由于我们使用的是整数(而不是无符号整数),这意味着 ebx 可以有一个大到 2,147,483,647 的数字。但是等等,如果将 2,147,483,647 * 10 相乘会怎样?好吧,因为 2,147,483,647 已经是您可以在寄存器中存储的最大数字,所以结果太大而无法放入 eax。所以乘法(总是)使用 2 个寄存器输出 mul
的结果。这就是 link 提到 "stores the result in EDX:EAX."
时的意思
所以,你可以这样写你的乘法:
int foo = 10, bar = 15;
int upper;
__asm__ ("mul %%ebx"
:"=a"(foo), "=d"(upper)
:"a"(foo), "b"(bar)
:"cc"
);
和以前一样,这将 bar 放入 ebx,将 foo 放入 eax,然后执行乘法指令。
并且在 asm 完成后,eax 将包含结果的下半部分,edx 将包含上半部分。如果 foo * bar < 2,147,483,647,则 foo 将包含您需要的结果,并且 upper
将为零。否则,事情会变得更复杂。
但这就是我愿意去的地方。除此之外,采用 asm class。读一本书。
PS 您也可以查看 this 答案,后面的 3 条评论说明为什么您的 "add" 示例也是 "wrong."
PPS 如果这个答案解决了您的问题,请不要忘记点击它旁边的复选标记,这样我就可以获得我的业力值。
考虑以下程序:
#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”的操作数数量不匹配
那么,为什么会出现此错误?我该如何解决这个错误?我在 google 上搜索过这些,但找不到解决我的问题的方法。我正在使用 windows 10 os & 处理器是 intel core i3.
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)。
我还要补充一点,使用内联汇编通常是 bad idea。
编辑:我无法将对您问题的回复放入评论中。
我不太确定从哪里开始。这些问题似乎表明您根本不了解汇编程序的工作原理。试图在 SO 答案中教你 asm 编程并不实用。
但我可以为您指明正确的方向。
首先,考虑一下这段asm代码:
movl , %eax
movl , %ebx
addl %ebx, %eax
你明白那是什么意思吗?完成后 eax 中会有什么? ebx中会有什么?现在,将其与此进行比较:
int foo = 10, bar = 15;
__asm__ __volatile__("add %%ebx,%%eax"
:"=a"(foo)
:"a"(foo), "b"(bar)
);
通过使用 "a" 约束,您要求 gcc 将 foo
的值移动到 eax 中。通过使用 "b" 约束,您要求它将 bar
移动到 ebx 中。它执行此操作,然后执行 asm 的指令(即 add
)。在退出 asm 时,foo
的新值将在 eax 中。明白了吗?
现在,让我们看看mul
。根据我 link 告诉你的文档,我们知道语法是 mul value
。这看起来很奇怪,不是吗? mul
怎么可能只有一个参数呢? 与的乘积是多少?
但是如果你继续阅读,你会看到 "Always multiplies EAX by a value." 啊。所以这里总是隐含 "eax" 寄存器。所以如果你要写 mul %ebx
,那实际上是 mul ebx, eax
,但是因为它总是 has 是 eax,所以写出来没有实际意义.
然而,它比那要复杂一点。 ebx 可以保存一个 32 位值的数字。由于我们使用的是整数(而不是无符号整数),这意味着 ebx 可以有一个大到 2,147,483,647 的数字。但是等等,如果将 2,147,483,647 * 10 相乘会怎样?好吧,因为 2,147,483,647 已经是您可以在寄存器中存储的最大数字,所以结果太大而无法放入 eax。所以乘法(总是)使用 2 个寄存器输出 mul
的结果。这就是 link 提到 "stores the result in EDX:EAX."
所以,你可以这样写你的乘法:
int foo = 10, bar = 15;
int upper;
__asm__ ("mul %%ebx"
:"=a"(foo), "=d"(upper)
:"a"(foo), "b"(bar)
:"cc"
);
和以前一样,这将 bar 放入 ebx,将 foo 放入 eax,然后执行乘法指令。
并且在 asm 完成后,eax 将包含结果的下半部分,edx 将包含上半部分。如果 foo * bar < 2,147,483,647,则 foo 将包含您需要的结果,并且 upper
将为零。否则,事情会变得更复杂。
但这就是我愿意去的地方。除此之外,采用 asm class。读一本书。
PS 您也可以查看 this 答案,后面的 3 条评论说明为什么您的 "add" 示例也是 "wrong."
PPS 如果这个答案解决了您的问题,请不要忘记点击它旁边的复选标记,这样我就可以获得我的业力值。