简体   繁体   English

'imul' 的操作数大小不匹配

[英]operand size mismatch for `imul '

although I use only longs for multiplication, Have no idea, why the operand size is wrong :虽然我只使用 long 进行乘法,但不知道为什么operand size is wrong

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

movl 8(%ebp), %ecx #the first and only argument
movl $1, %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

That's a bogus error message.这是一个虚假的错误信息。 It's not operand size that's the problem, it's that imul 's destination has to be a register.问题不是操作数大小,而是imul的目标必须是寄存器。 https://www.felixcloutier.com/x86/imul . https://www.felixcloutier.com/x86/imul Only the source can optionally be memory.只有可以选择为 memory。

(AT&T syntax is op src, dst , opposite of Intel's manuals which use Intel syntax.) (AT&T 语法是op src, dst ,与使用 Intel 语法的 Intel 手册相反。)

When you get an error that doesn't make sense, you should consult an ISA reference and make sure the instruction you want is actually encodeable: it's not unheard of for assemblers to print an error message that doesn't properly explain why an instruction can't be assembled.当你得到一个没有意义的错误时,你应该查阅 ISA 参考并确保你想要的指令实际上是可编码的:汇编程序打印一个不能正确解释为什么指令可以的错误消息并不是闻所未闻的。不被组装。 But usually it's either an ambiguous operand-size or that the encoding you want doesn't exist.但通常它要么是不明确的操作数大小,要么是您想要的编码不存在。

Perhaps GAS internals treat a memory destination as having unknown or some random size, and nothing kicks in to imply a size for that operand the way it would for add %reg, (mem) .也许 GAS 内部将 memory 目标视为具有未知或一些随机大小,并且没有任何东西像add %reg, (mem)那样暗示该操作数的大小。 Maybe because imul doesn't have a memory-destination form.也许是因为imul没有记忆目的地形式。


Keep your local variables in registers like a normal person.像普通人一样将局部变量保存在寄存器中。 You only need to spill a variable to a slot on the stack when you run out of registers.当您用完寄存器时,您只需要将变量溢出到堆栈上的插槽。

EAX, ECX, and EDX are call-clobbered in the normal calling conventions so you can use them without saving/restoring. EAX、ECX 和 EDX 在正常调用约定中被调用破坏,因此您可以在不保存/恢复的情况下使用它们。 (EBX is call-preserved so your function is already violating the calling convention by destroying its caller's EBX value.) (EBX 是保留调用的,因此您的 function 已经破坏了调用者的 EBX 值,从而违反了调用约定。)


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

Never write a conditional branch over a jmp .永远不要jmp上写条件分支。 Instead do jne top_of_loop to either keep looping or fall through.而是执行jne top_of_loop以保持循环或失败。


IDK what your loop is supposed to do. IDK 你的循环应该做什么。 You didn't initialize your memory destination.您没有初始化 memory 目标。 Did you think it was going to store the result of ebx*ebx into memory?您是否认为它将ebx*ebx的结果存储到 memory 中? If so, why copy EAX to EBX in the first place?如果是这样,为什么首先将 EAX 复制到 EBX?

It looks like you're searching for the sqrt of a number, not just squaring a number, so the function name is weird.看起来您正在搜索一个数字的 sqrt,而不仅仅是一个数字的平方,所以 function 的名称很奇怪。 If so, you probably want jb as your loop condition to keep looping while x*x < target , and sort out equal vs. above after the loop.如果是这样,您可能希望jb作为您的循环条件,以在x*x < target时继续循环,并在循环后排序 equal vs. above。 (In case the function is called with an arg that isn't a perfect square.) (如果 function 被调用的 arg 不是一个完美的正方形。)

.globl find_exact_sqrt
find_exact_sqrt:

    mov   4(%esp), %ecx    # target number
    mov   $1, %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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM