【问题标题】:MUL instruction doesn't support an immediate valueMUL 指令不支持立即数
【发布时间】:2010-12-25 04:09:15
【问题描述】:

我已经阅读了一些教程和示例,但我无法理解MUL 指令的工作原理。我使用ADDSUB 没有问题。显然,这条指令将其操作数乘以寄存器中的值。

第一个操作数乘以哪个寄存器(eax、ebp、esp 等)?结果存储在哪个寄存器中,所以我可以将它移到堆栈中?抱歉,我只是在学习 x86 汇编。

当我尝试编译这一行时...

mul     9

我明白了,Error: suffix or operands invalid for 'mul'。谁能帮帮我?

    global  main
    main:
    push    ebp
    movl    ebp, esp
    sub     esp, byte +8
    mov     eax, 7
    mul     9
    mov     [esp], eax
    call    _putchar
    xor     eax, eax
    leave
    ret

【问题讨论】:

    标签: assembly x86 immediate-operand


    【解决方案1】:

    MUL 不能使用立即数作为参数。例如,您必须将“9”加载到寄存器中,

     movl    $7, %eax
     movl    $9, %ecx
     mull    %ecx
    

    这会将 eax 乘以 ecx 并将 64 位乘积存储在 edx:eax 中。

    英特尔网站上有一个很好的综合参考 x86 汇编指令,请参阅此处

    http://www.intel.com/Assets/PDF/manual/253666.pdf

    http://www.intel.com/Assets/PDF/manual/253667.pdf

    但这可能是您现在需要的更多信息。

    【讨论】:

    • OP 没有使用 EDX 高半结果。您至少应该提及 x86 确实具有立即乘法(在 386 之前的某个时间添加,因此 32 位代码始终可以依赖它)。 imul $9, %eax, %eax。或者更好的 2 次幂 + 1 lea (%eax, %eax, 8), %eax
    【解决方案2】:

    如果您查看MUL 格式表,您会注意到它只接受一个寄存器参数。但是转到IMUL,你会看到它有很多形式可以接受立即数

    6B /r ib IMUL r16, r/m16, imm8 字寄存器 ← r/m16 * 符号扩展立即字节。 6B /r ib IMUL r32, r/m32, imm8 双字寄存器 ← r/m32 * 符号扩展立即字节。 REX.W + 6B /r ib IMUL r64, r/m64, imm8 四字寄存器 ← r/m64 * 符号扩展立即字节。 69 /r iw IMUL r16, r/m16, imm16 字寄存器 ← r/m16 * 立即字。 69 /r id IMUL r32, r/m32, imm32 双字寄存器 ← r/m32 ∗ 立即双字。 REX.W + 69 /r id IMUL r64, r/m64, imm32 四字寄存器 ← r/m64 * 立即双字。

    所以要将 eax 乘以 9,你可以这样做

    mov eax, 7
    imul eax, eax, 9 ; eax = eax*9
    

    仔细观察,您还可以观察到这些版本没有变宽。事实上,现在imul 专门用于几乎所有乘法,因为非扩展乘法是 the same for signed and unsigned values 并且高级语言中的乘法是非扩展的(即输出类型和输入操作数的类型相同),除非你将操作数转换为更广泛的类型。结果,modern x86 CPUs are often optimized for imul 也比mul 多了很多形式

    【讨论】:

    • 在这种 2 + 1 的幂的情况下,lea eax, [eax + eax*8] 甚至比直接 imul 更好。但是,是的,+1,当 OP 显然没有使用高半结果时,我无法相信所有这些建议 mov 进入寄存器的答案。
    【解决方案3】:

    http://siyobik.info/index.php?module=x86&id=210

    目标操作数是隐含的 操作数位于寄存器 AL、AX 或 EAX(取决于 操作数);源操作数是 位于通用寄存器中 或内存位置

    结果存储在寄存器AX中, 寄存器对 DX:AX,或寄存器对 EDX:EAX(取决于操作数 大小),与的高阶位 产品包含在寄存器 AH、DX、 或EDX,分别。如果 乘积的高位为 0, CF 和 OF 标志被清除; 否则,设置标志。

    在您的来源中应该是 mul 而不是 mull

    【讨论】:

      【解决方案4】:

      我不是专家,但我认为您的问题是 mul 在您的情况下不接受直接操作数十进制常量 9,因此请尝试将 9 放入假设寄存器 bx 中,如下所示:

      mov bx, 9
      mul bx
      

      要回答您关于mul 的问题,一般看起来像这样:

      mul     reg/memory
      

      然后这样做:

      dx:ax := ax*reg/mem
      

      因此,它需要一个操作数,该操作数应该是寄存器或内存位置(存储要相乘的值,因此本质上是一个变量)并将其乘以 ax,然后取决于寄存器/内存的长度(所以您提供的操作数)将其存储在 ax 或 dx:ax 或 edx:eax 中

      希望我能帮到你!

      【讨论】:

        【解决方案5】:

        我会给你一个链接,指向我最喜欢的、易于阅读但完整的 x86 参考:http://www.ousob.com/ng/iapx86/ng1840d.php

        【讨论】:

        • 这无论如何都不能回答这个问题。并且不鼓励仅提供链接的答案
        【解决方案6】:

        如何阅读英特尔手册以了解它是不可能的

        首先下载英特尔手册。当前下载页面是:http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html 但只是谷歌“intel x86 手册”,因为它一定会改变。

        我们想要的是包含所有指令的组合第 2 卷指令集参考 A-Z。

        在该手册中,找到DIV 的文档。我们看到DIVInstruction栏下有如下形式:

        • DIV r/m8
        • DIV r/m16
        • DIV r/m32
        • DIV r/m64

        r/mX 表示它可以占用大小为 X 的寄存器或内存位置。

        因此,没有任何形式采用immX,它是一个立即数或文字。

        因此不可能将该指令编码到处理器,现在我们知道唯一的方法是通过寄存器或内存。

        寄存器更快,所以我们当然会尽可能使用它们。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-05-20
          • 2022-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多