我可以将寄存器的值乘以立即数来将结果添加到另一个寄存器吗?

时间:2013-09-15 02:39:08

标签: linux assembly x86 nasm

使用NASM学习装配,Ubuntu,32位。

.data中的我的数组:

ary db 1,2,2,4,5 ; Five elements of one byte each

还有一些数字:

tmp db 2   ; Holds the number 2

假设我想在数组中的索引4处打印元素(因此它将是5)。

我知道我可以这样做:

mov EAX,4
mov EBX,0
mov ECX,ary          ; Put the array's address in ECX
add ECX,4            ; Move address four bytes to the right
add byte [ECX],'0'   ; The value at this address to ASCII
mov EDX,1
int 0x80

然而,无论出于何种原因,我决定不是写常数4,而是想通过将我的变量(2)乘以2来实现。< / p>

这是更新的代码:

mov EAX,[tmp]   ; Put the number 2 in EAX
mov ECX,ary     ; Put the array's address in ECX
add ECX,EAX * 2 ; Move (2 * 2) = 4 bytes to the right
add byte [ECX],'0' ; Decimal to ASCII
mov EAX,4
mov EBX,0
mov EDX,1
int 0x80

这不适用于add ECX,EAX * 2

invalid operand type

但为什么呢? ECX评价不到2?相当于

add ECX,2 * 2

奇怪的是,这些确实有效:

add ECX,EAX * 1   ; Moves by 2
add ECX,EAX * 0   ; Moves by 0

以上建议我答案是否定的。而乘以10的原因是因为汇编程序实际上并不需要进行任何乘法来首先知道答案。

这是否意味着为了达到我的目的,我必须使用mul指令?

3 个答案:

答案 0 :(得分:4)

如果您使用lea

,您可以执行乘法并添加一条指令
lea ECX,[ECX+EAX*2]

答案 1 :(得分:2)

在x86中,尽管lea支持乘以常数,但add指令不支持将寄存器乘以常量的操作数。它支持附加偏移,但不支持乘法。正如你所指出的那样,我假设汇编程序在这种情况下在add ECX,EAX*0add ECX,EAX*1的公认语法中有点宽容,分别等同于add ECX,0add ECX,EAX

你需要做这样的事情:

mov ECX,ary     ; Put the array's address in ECX
mov EAX,[tmp]   ; Put the number 2 in EAX
shl EAX,1       ; (instead of mul EAX,2)
add ECX,EAX     ; Move (2 * 2) = 4 bytes to the right
add byte [ECX],'0' ; Decimal to ASCII
mov EAX,4
mov EBX,0
mov EDX,1
int 0x80

答案 2 :(得分:1)

指令LEA可用于一次提供两个加法和一个有限乘法。常用语法是:

lea reg, [offset+reg+const*reg]

此处,reg是任何寄存器,offset是一些常数,const是1,2,4或8常数之一。

这样,这条指令非常强大,是为了计算一些相当复杂的方程式:

问题中的等式:

add ECX,EAX * 2

可以这样计算:

lea ecx, [ecx+2*eax]

还有许多其他用途:

lea  eax, [ebx+2*ebx] ; eax = 3*ebx
lea  eax, [eax+4*eax] ; eax = 5*eax
lea  eax, [ecx+8*ecx] ; eax = 9*ecx
lea  eax, [1234+ebx+8*ecx]

请注意,FASM允许上述示例的语法更短:

lea  eax, [3*ebx]
lea  eax, [5*eax]
lea  eax, [9*ecx]

lea指令的另一个优点是它不会影响标志。在所有x86 CPU上,该指令的执行速度非常快。