Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在AT&;中有没有一种简单的方法可以将这样的两个寄存器相乘;T程序集:%eax*%ebx=%ecx_Assembly_X86_Att - Fatal编程技术网

Assembly 在AT&;中有没有一种简单的方法可以将这样的两个寄存器相乘;T程序集:%eax*%ebx=%ecx

Assembly 在AT&;中有没有一种简单的方法可以将这样的两个寄存器相乘;T程序集:%eax*%ebx=%ecx,assembly,x86,att,Assembly,X86,Att,我正在尝试使用AT&T/GAS语法将for循环从C转换为汇编: for(int j = i; i*j < N; j++) { A[i*j] = 0; } for(int j=i;i*j

我正在尝试使用AT&T/GAS语法将for循环从C转换为汇编:

for(int j = i; i*j < N; j++) {
    A[i*j] = 0;
}
for(int j=i;i*j
我将I存储在%eax中,将j存储在%ebx中。我遇到的问题是,实际上要将Ij相乘,因为指令imul“reg32”,“reg32”将结果存储在第二个寄存器中,这显然是我不想要的。我想要的是能够将结果存储在另一个寄存器中,比如说%ecx,然后使用它访问索引I*j处数组中的值

当我查找指令imul的用法时,似乎无法实际将两个寄存器相乘并将结果存储在第三个寄存器中。当然,我可以做一个循环,做一些加法等等,但这似乎是无效的,而且不是这样做的方式。请注意,我对assembly完全陌生(只使用了几天),因为我们刚刚开始学习CS课程的基础知识

TL;DR

将存储在两个寄存器中的值相乘的最佳方法是什么:%eax*%ebx=%ecx

当我查找指令imul的用法时,似乎没有办法将两个寄存器相乘并将结果存储在第三个寄存器中

大多数x86指令都是这样的——大多数算术和逻辑运算采用两个操作数,并将结果存储回一个源寄存器。如果需要保存一个原始值,请将其复制到另一个寄存器

imul
是一条特别奇怪的x86指令,因为它有一个单参数形式,将源寄存器乘以
eax
,并将结果写入
edx:eax
。这些寄存器映射不灵活;如果您需要完整的产品,您需要围绕此分配您的寄存器

当然,我可以做一个循环,做一些加法等等,但这似乎是无效的,而且不是这样做的方式


这实际上是一个很好的方法——加法比乘法快。一个好的优化编译器可能会沿着这些思路做一些事情。

您想要观察的是
i*j
随着
j
的增加而变化的方式。所以,让我们假设
i
50
,那么最初
j=50
,所以
i*j
50*50
。循环的下一次迭代,
j
51
,因此
i*j
50*51
,或者,
50*(50+1)
,或者,
50*50+50
。接下来的迭代,
i*j
50*50+50+50
,依此类推

通过保留一个累加器,在
j
循环外部/之前使用
i*i
初始化,并在每次循环迭代中使用一条简单的add指令进行维护,您可以在不进行乘法的情况下获得
i*j
的值

另见


我强烈怀疑,如果您查看外部
I
循环(问题中未显示),您将能够消除初始乘法(这里是初始化累加器的第一个
I*I
)。

x86是一种双操作数体系结构,其中大多数指令采用两个操作数,覆盖其中一个操作数。如果要将结果写入第三个操作数,而不是覆盖一个源操作数,标准解决方案是首先将其中一个操作数移动到目标,然后将目标与两个操作数指令一起使用。例如,要将
eax
ebx
相乘,将结果放入
ecx
,您需要

mov %ebx, %ecx
imul %eax, %ecx
尽管正如其他人所指出的,对于你的循环来说,最好完全放弃乘法,而是承认你可以做加法。你的循环

for (int j = i; i*j < N; j++) {
    A[i*j] = 0;
}
for(int j=i;i*j
可以重写为

A_ = A + i * i;
N_ = N - i * i;
for (j = 0; j < N_; j += i)
    A_[j] = 0;
A_u=A+i*i;
N_uu=N-i*i;
对于(j=0;j
在循环中不需要乘法。

指令imul“reg32”,“reg32”将结果存储在第二个寄存器中,这显然是我不想要的。为什么你显然不想要这个?正确的方法是
imul%eax,%ebx
然后,如果需要
%ecx
中的结果,可以执行
mov%eax,%ecx
。如果需要在
%eax
中保留该值,可以将其保存(例如,在堆栈上)。当我查找指令imul的用法时,似乎没有办法将两个寄存器相乘并将结果存储在第三个寄存器中。这是真的。但这并不麻烦。
imul
有一个单操作数形式,但通常只有在需要高半结果时才应该使用该形式。它的速度较慢(分割结果并将高半部分写入EDX的额外uop),并且通常需要额外的指令才能从累加器获取数据。如果您只需要一个正常的截断32x32=>32位乘法,请使用2操作数形式。(或者使用一个立即数,即3操作数
imul r32,r/m32,imm
)您的措辞似乎暗示您实际使用的是
imul r/m32
,而不是
imul r32,r/m32
,但您只能在16位代码中对8086 compat执行此操作。