【问题标题】:Incorrect value of the variable ans that stores the LCM of two numbers (8086 Program)变量值不正确且存储两个数字的 LCM(8086 程序)
【发布时间】:2021-02-20 01:01:19
【问题描述】:

以下是我编写的用于在 EMU8086 中查找两个数字的 LCM 的代码。当我运行它时,我在 Ans 变量中得到值 0。

.MODEL SMALL 
.DATA 
Num1 DW 250 
Num2 DW 100
Ans DW ? 
.CODE 
MOV AX,@DATA 
MOV DS, AX 
MOV AX, Num1 
MOV BX, Num2 
MOV DX, 0000h 
NEXT: PUSH AX 
PUSH DX 
DIV BX 
CMP DX, 0000h 
JZ LAST 
POP DX 
POP AX 
ADD AX, Num1 
JNC NEXT 
INC DX 
JMP NEXT 
LAST: POP Ans+2 
POP Ans 
MOV AH, 4Ch 
INT 21h 
END

【问题讨论】:

  • 不知道是不是和this有关? emu8086 在其DIV 的实现中似乎存在错误。你用其他模拟器测试过吗?
  • 一个注释,不过;我没有仔细阅读代码,但您似乎在AnsAns+2 存储了两个结果字。但是,Ans 只分配了一个字,因此pop Ans+2 将覆盖其他内容。不确定这是否是您的错误,但它看起来不对。
  • 另外,这是一个非常荒谬的寻找 LCM 的算法;重复将Num1 添加到自身,直到它是Num2 的倍数。您可能会查找“欧几里得算法”以获得更有效的方法。

标签: x86-16 emu8086 lcm


【解决方案1】:

LCM(a, b) = a * b / GCD(a, b)

由于这个方程,您可以使用欧几里德算法找到 GCD,然后计算 LCM。假设数字 a 和 b 在 al 和 dl 中,此代码计算 LCM。

; Save multiplication value
MOV AL, DL ; This 2 lines is AL * DH
MUL DH
PUSH AX ; Store result in stack

FINDBCD: ; General idea is : LCM(a, b) = a*b/BCD(a,b)
    ; We calculate BCD with euclidean algorithm
    CMP DH, DL
    JNS CALCULATE ; Jump if DL < DH else swap them
    MOV CL, DL ; This 3 line swap DL and DH
    MOV DL, DH
    MOV DH, CL
    CALCULATE:
    MOV AL, DH ; Move greater number in AL
    XOR AH, AH ; Zero AX 8 second bits
    DIV DL ; This is AL/DL
    CMP AH, 0 ; If remainder is zero so we found BCD
    JE AFTERFINDBCD
    SUB DH, DL ; Else substract smaller number from greater number
    JMP FINDBCD ; Do this until find BCD

AFTERFINDBCD:
    CMP DH, DL 
    JNS FINDLCM ; Jump if DL < DH
    MOV CL, DL ; This 3 line swap DL and DH
    MOV DL, DH
    MOV DH, CL

FINDLCM:
    POP AX ; Retreive multiplication result
    DIV DL ; This is AX/DL
    AND AX, 0000000011111111B ; Ignore remainder

【讨论】:

  • 这需要两个 8 位输入。该问题具有 16 位输入,因此 LCM 可能大于 16 位。正如 Brett Hale pointed out 在相关问题上一样,您可以使用 (a / gcd) * b 以扩大 mul 结尾,因为根据定义,a 可以被 GCD 整除。请参阅 Brett 对该链接问题的回答;用 16 位 regs 做同样的事情应该适用于 OP。
  • 如果你真的只想交换 DL 和 DH 而不在其他任何地方留下副本,xchg dh,dl 至少在几乎所有 CPU 上都一样高效,在真正的 8086 上效率更高。另外,and ax, 0x00ff很傻:像之前一样使用mov ah,0xor ah,ah
  • CMP / JNS 不是您如何检查哪个更大。你想要ja 上面的未签名。 ns 条件只检查减法结果的 MSB,这仅在数字很小或附近被解释为有符号整数时才有效(并且没有发生有符号溢出)。您正在使用未签名的div,因此您应该使用未签名的分支条件。
  • 请注意,标准 GCD 在循环中只需要 2 个 mov 指令:Greatest Common Divisor
  • 感谢您的 cmets 我没有专业地使用汇编,实际上我自己并不认识其中的大部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2013-06-16
相关资源
最近更新 更多