首页 > 解决方案 > x86-16 imul 指令“参数错误”?

问题描述

所以,我有这样的代码:

    XOR DX, DX
    MOV BX, 1
    MOV AX, BX
    MOV CX, 10
.LOOP:
    JCXZ .EXIT_LOOP
    IMUL AX, 34     ; in here
    SUB AX, DX
    ADD AX, 2
    PUSH AX
    INC DX
    DEC DX
    XCHG BX, DX
    MOV BX, [SP]
    LOOP .LOOP
.EXIT_LOOP:

我不知道,在 16 位寄存器IMUL指令中,emu8086 中会出现这样的错误。

如果使用 32 位寄存器IMUL EAX, 34(不在 emu8086 中)应该没问题。

我该如何解决这个问题?

标签: assemblyx86-16emu8086

解决方案


IMUL指令、操作码6B和的立即数形式69实际上采用三个操作数,它们的大小都相同(此处为 16 位):IMUL r, r/m, imm. 它将第二个操作数乘以第三个并将结果放在第一个操作数中,在溢出的情况下截断。最初的 8086 不支持这种形式,但在80186中作为扩展添加,大约在 1982 年,并且已被所有较新的 x86 处理器支持。

您的 32 位汇编器显然支持将EAX 用作源操作数和目标操作数的IMUL EAX, 34语法糖。IMUL EAX, EAX, 34

所以这里有三种可能性;我对emu8086一无所知,所以不确定哪个适用。

  • 也许您的 emu8086 仿真器/汇编器确实支持 186 条指令,但不支持语法糖。在这种情况下,您只需要编写IMUL AX, AX, 34.

  • 或许 emu8086 当前设置为仅支持原始 8086 指令集,但有一些选项可以添加 186 扩展。在这种情况下,一旦启用该选项,您应该能够使用所需的指令,可能使用上面列出的三操作数语法。

  • 或者也许emu8086,顾名思义,只支持8086指令集,句号。在这种情况下,您必须重写代码以使用单操作数形式IMUL r/m,并将常量 34 加载到寄存器中(或将其放在内存中)。请注意,它IMUL r/m正在扩大并将其 32 位结果放入中,因此如果结果为负数或大于 32767,则DX:AX您的零值将被破坏;DX您需要相应地调整您的代码。

    或者用 shift 和 add 重写它,这可能更有效:x * 34 == (x << 5) + (x << 1). 或者,当然,您可以找到另一个支持 186 条指令的仿真器。


推荐阅读