Assembly 在AT&;中有没有一种简单的方法可以将这样的两个寄存器相乘;T程序集:%eax*%ebx=%ecx
我正在尝试使用AT&T/GAS语法将for循环从C转换为汇编: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
for(int j = i; i*j < N; j++) {
A[i*j] = 0;
}
for(int j=i;i*j
我将I存储在%eax中,将j存储在%ebx中。我遇到的问题是,实际上要将I和j相乘,因为指令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执行此操作。