“imul”的操作数大小不匹配

operand size mismatch for `imul '

虽然我只使用 longs 进行乘法运算,但不知道为什么 operand size is wrong:

.type _square, @function
_square:
pushl %ebp
movl %esp, %ebp
subl , %esp #room for the local variable

movl 8(%ebp), %ecx #the first and only argument
movl , %eax

_finding_loop:
incl %eax
movl %eax, %ebx
imull %ebx, -4(%ebp) #storing the result in local var
cmpl -4(%ebp), %ecx #compare with the argument
je _found #epilogue and returning
jmp _finding_loop

这是一条虚假的错误信息。这不是操作数 size 的问题,而是 imul 的目的地必须是寄存器。 https://www.felixcloutier.com/x86/imul。只有来源可以选择内存

(AT&T 语法是 op src, dst,与使用 Intel 语法的 Intel 手册相反。)

当你得到一个没有意义的错误时,你应该查阅 ISA 参考并确保你想要的指令实际上是可编码的:汇编程序打印不正确的错误消息并非闻所未闻解释为什么一条指令不能被汇编。但通常是操作数大小不明确,或者您想要的编码不存在。

也许 GAS 内部将内存目的地视为具有未知或一些随机大小,并且没有任何东西像 add %reg, (mem) 那样暗示该操作数的大小。可能 因为 imul 没有内存目标形式。


像普通人一样将局部变量保存在寄存器中。当您 运行 超出寄存器时,您只需要将变量溢出到堆栈上的插槽。

EAX、ECX 和 EDX 在正常调用约定中被调用破坏,因此您可以在没有 saving/restoring 的情况下使用它们。 (EBX 是调用保留的,因此您的函数已经破坏了调用者的 EBX 值,从而违反了调用约定。)


cmpl -4(%ebp), %ecx #compare with the argument
je _found #epilogue and returning
jmp _finding_loop

切勿在 上写条件分支 jmp。相反,jne top_of_loop 要么继续循环要么失败。


不知道你的循环应该做什么。您没有初始化您的内存目的地。你以为它会把 ebx*ebx 的结果存储到内存中吗?如果是这样,为什么首先将 EAX 复制到 EBX?

看起来你在搜索一个数的平方,而不仅仅是一个数的平方,所以函数名很奇怪。如果是这样,您可能希望 jb 作为您的循环条件,以便在 x*x < target 时继续循环,并在循环后对 equal 与 above 进行排序。 (以防使用不是完美正方形的 arg 调用函数。)

.globl find_exact_sqrt
find_exact_sqrt:

    mov   4(%esp), %ecx    # target number
    mov   , %eax         # start searching from 2*2=4

.Lloop:       # file-local label, not exported in the symbol table
                         # do {
    inc   %eax
    mov   %eax, %edx
    imul  %edx, %edx       # eax squared
    cmp   %ecx, %edx
    jb    .Lloop         # }while(i*i < target); // unsigned

    ret