我试图在汇编中解决这些简单的乘法和除法运算。
5*4 + 35/7
我已经这样做了
mov al,5
mov bl,4
mul bl
mov ax,35
mov bl,7
div bl
我之前在AX寄存器中的乘法值被除法的新结果覆盖。我该如何解决?
我试图在汇编中解决这些简单的乘法和除法运算。
5*4 + 35/7
我已经这样做了
mov al,5
mov bl,4
mul bl
mov ax,35
mov bl,7
div bl
我之前在AX寄存器中的乘法值被除法的新结果覆盖。我该如何解决?
我之前在 AX 寄存器中的乘法值被除法的新结果覆盖。我该如何解决?
很简单。将乘法的结果放在一个额外的寄存器中(我用过DX
),计算表达式的下一项,最后将两个结果相加。需要注意的是,商只在寄存器中,所以在做加法之前AL
需要先清除寄存器!AH
(示例“35/7”中使用的数字产生的余数为 0,AH
但当被要求编写程序时,您不应该指望它!)
mov al,5
mov bl,4
mul bl ; -> Result is in AX
mov dx, ax
mov ax,35
mov bl,7
div bl ; -> Result is in AL
mov ah, 0
add ax, dx ; -> Final result is in AX
Emu8086 基于 8086 指令,因此您只有MUL和DIV的单操作数版本。只是为了让您知道,IMUL是MUL的签名版本,IDIV是DIV的签名版本。假设您打算进行无符号运算,您的代码可能如下所示:
mov al,5
mov bl,4
mul bl
mov cx, ax ; Save AX to CX
mov ax,35
mov bl,7
div bl
xor ah, ah ; Result(quotient) of DIV in AL, ensure AH is zero
add ax, cx ; AX=AX+CX
使用MUL和DIV的 8086 特定指令无法防止AX被破坏。您必须将值移动到暂存区域。我们将在上面的代码中使用寄存器CX。由于我们将MUL指令的结果保存到CX,我们只需将其添加到DIV指令的结果中(其中商在AL中)。我们将存储在AH中的余数归零,将商留在AL中。AX现在将包含我们添加到CX的商(作为 16 位值), 等式的最终结果存储在AX中。
乘以 4 的一种简化是将值左移 2 位。这段代码:
mov al,5
mov bl,4
mul bl
mov cx, ax ; Save AX to CX
可以简化为:
mov cx, 5
shl cx, 2 ; Multiply CX by 4
8086 处理器不支持SHL移位超过 1 位,除非通过CL寄存器。EMU8086 的汇编器自动将SHL reg, imm
指令翻译成一条或多SHL, reg, 1
条指令。在这种情况下SHL CX, 2
被翻译成:
shl cx, 1 ; Multiply CX by 2
shl cx, 1 ; Multiply CX by 2 again
大多数 8086 汇编器不会为您进行这种翻译。或者,可以在CL寄存器中指定要移位的位数。这(或等效的)适用于大多数 8086 汇编器:
mov cl, 2 ; Number of bits to shift left by in CL
mov dx, 5
shl dx, cl ; Shift DX to the left by CL(2) is equivalent to multiply by 4
mov ax,35
mov bl,7
div bl
xor ah, ah ; Result(quotient) of DIV in AL, ensure AH is zero
add ax, dx ; AX=AX+DX
您需要将 5 * 4 相乘,然后将值压入堆栈。然后进行第二次计算,除法。然后从堆栈中弹出第一个值并将这些值相加。
要回答主要问题:您可以使用imul reg, reg, imm
将乘法运算到不同的寄存器中。或者您可以mov ecx, eax
将结果保存在不需要的寄存器中div
。
由于您没有说明数据必须来自哪里,因此显而易见的事情是在组装时执行计算。
mov eax, 5*4 + 35/7
如果您仍想在运行时进行计算,则需要从立即数、寄存器或内存中的值开始。在这里说明它们的混合很方便(因为div
没有立即操作数形式)
通常最好使用默认操作数大小,在 32 和 64 位模式下为 32 位。不过,8 位运算通常并不慢。
mov eax, 35
div byte [seven] ; al = ax/7, ah=ax%7. wider operand sizes divide edx:eax by the src.
mov cl, 5
lea eax, [ecx*4 + eax] ; al = cl*4 + al. Ignore the garbage in the high bits.
; result in al
section .rodata
seven: db 7
div
速度很慢,因此编译器将除以常量替换为乘以时髦的常量,并移位结果,因为这可能与 2 的补码溢出有关。
如果只需要结果的低部分,请参阅哪些 2 的补码整数运算可以在不将输入中的高位归零的情况下使用?为了证明使用lea
乘以 4 并相加,而不清除高位。