2

我试图在汇编中解决这些简单的乘法和除法运算。

5*4 + 35/7

我已经这样做了

mov al,5
mov bl,4 
mul bl 

mov ax,35 
mov bl,7 
div bl

我之前在AX寄存器中的乘法值被除法的新结果覆盖。我该如何解决?

4

4 回答 4

2

我之前在 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
于 2016-01-30T14:31:12.433 回答
2

Emu8086 基于 8086 指令,因此您只有MULDIV的单操作数版本。只是为了让您知道,IMULMUL的签名版本,IDIVDIV的签名版本。假设您打算进行无符号运算,您的代码可能如下所示:

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

使用MULDIV的 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
于 2016-01-30T10:09:50.220 回答
1

您需要将 5 * 4 相乘,然后将值压入堆栈。然后进行第二次计算,除法。然后从堆栈中弹出第一个值并将这些值相加。

于 2016-01-30T06:57:00.067 回答
1

要回答主要问题:您可以使用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 并相加,而不清除高位。

于 2016-01-30T07:39:57.737 回答