2

So, I have code like this :

    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:

I don't know, in 16-bit register IMUL instruction give me an error like this in emu8086.

It should be fine if use 32-bit register like IMUL EAX, 34 (not in emu8086).

How I can fix this ?

vbvbvb123
  • 31
  • 4
  • The immediate-form imul instruction takes three operands, so you might try writing `IMUL AX, AX, 34`. I don't know why two operands would work for the 32-bit form and not the 16-bit form; possibly a bug in emu8086's assembler. I don't have it installed here so I can't test it. Another possibility is that you are in a mode where you are emulating a true 8086, on which the immediate form of `IMUL` did not exist; I believe it was introduced with the 80186. When you write the 32-bit form you are obviously assuming an 80386 or higher, which would support the immediate form. – Nate Eldredge Oct 16 '20 at 14:13
  • @NateEldredge ooopss... see my edit – vbvbvb123 Oct 16 '20 at 14:35
  • 1
    Okay, so then you have to figure out what emu8086 is emulating. If it's an 80186 or higher, the instruction should exist and you may be able to assemble it with `IMUL AX, AX, 34`. If it's an 8086, then you don't have an immediate multiply instruction and you will have to use the one-operand r/m form, loading 34 into a register first. Note that the one-operand form is widening and will overwrite DX with the high half of the result. – Nate Eldredge Oct 16 '20 at 14:42
  • Related: [Is it possible to multiply by an immediate with mul in x86 Assembly?](https://stackoverflow.com/q/20499141) - the answer there now mentions that imul-immediate requires 186, but not really a duplicate. Also [What's 'new' in a 'new' processor when viewed from programmer's point](https://stackoverflow.com/q/53853777) uses `imul` as an example. – Peter Cordes Oct 16 '20 at 20:46

1 Answers1

2

The immediate form of the IMUL instruction, opcodes 6B and 69, actually takes three operands, all of the same size (here 16 bits): IMUL r, r/m, imm. It multiplies the second operand by the third and places the result in the first, truncating in case of overflow. This form was not supported by the original 8086, but was added as an extension in the 80186, circa 1982, and has been supported by all newer x86 processors.

Your 32-bit assembler apparently supports IMUL EAX, 34 as syntactic sugar for IMUL EAX, EAX, 34, with EAX used as both a source and destination operand.

So there are three possibilities here; I don't know anything about emu8086 so am not sure which one applies.

  • Perhaps your emu8086 emulator/assembler does support 186 instructions, but not the syntactic sugar. In this case you simply need to write IMUL AX, AX, 34.

  • Perhaps emu8086 is currently set to support only the original 8086 instruction set, but has some option to add the 186 extensions. In that case, once you enable that option, you should be able to use your desired instruction, possibly with the three-operand syntax listed above.

  • Or perhaps emu8086, as its name suggests, only supports the 8086 instruction set, period. In that case you have to rewrite your code to use the one-operand form IMUL r/m, and load your constant 34 into a register (or place it in memory). Note that IMUL r/m is widening and will place its 32-bit result into DX:AX, so your zero value in DX will be clobbered if the result is negative or larger than 32767; you'll need to adapt your code accordingly.

    Or rewrite it with shifts and adds which may be more efficient anyway: x * 34 == (x << 5) + (x << 1). Or, of course, you can find another emulator that does support 186 instructions.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • 3
    EMU8086 emulates an 8086 but it does support some 80186. It supports pusha/popa and push immediate. bit shifting instructions support immediates other than 1 but they get translated to multiple 1 bit operations. so `shl ax, 4` would be 4 `shl ax, 1` . It only supports the one operand form of IMUL. So it is more than an 8086 and less than an 80186 – Michael Petch Oct 17 '20 at 02:27
  • 2
    @MichaelPetch: Interesting, and bizarre. – Nate Eldredge Oct 17 '20 at 02:54
  • 2
    @NateEldredge: It also has confusing behaviour like letting `mov [si], 1234h` [imply word operand size](https://stackoverflow.com/questions/49910109/why-operand-must-have-size-in-one-line-but-not-the-other-in-x86-assembly); I wouldn't recommend it to anyone, especially just learning asm. (Although mostly because it's a DOS / 8086 emulator which is already a terrible way to start learning asm, IMO.) But I seem to recall some other instances of poorly-designed behaviour, and maybe unhelpful error messages (I forget), that have come up for emu8086 in past x86 questions. overall opinion = low. – Peter Cordes Oct 17 '20 at 08:59