gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 06:17:32 26 4
gpt4 key购买 nike

考虑以下程序:

#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。

最佳答案

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 编程并不实际。

但我可以为您指明正确的方向。

首先,考虑一下这段 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)
);

通过使用“a”约束,您要求 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"
);

和以前一样,这将 bar 放入 ebx 并将 foo 放入 eax,然后执行乘法指令。

并且在 asm 完成后,eax 将包含结果的下半部分,edx 将包含上半部分。如果 foo * bar < 2,147,483,647,则 foo 将包含您需要的结果并且 upper 将为零。否则,事情会变得更加复杂。

但这就是我愿意去的地方。除此之外,参加asm类(class)。读一本书。

PS 你也可以看看 this答案和后面的 3 条评论说明了为什么即使您的“添加”示例也是“错误的”。

PPS 如果这个答案解决了您的问题,请不要忘记点击它旁边的复选标记,以便我获得我的业力积分。

关于c - 内联汇编中的乘法指令错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42264712/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com