-1

Hi I am just playing around in 64 bit assembly but my compiler keeps throwing :(13: Invalid combination of opcode and operands) can anyone explain why this is happening thanks.

10:  myfunc:
11:    mov  rax, rcx
12:    xor  rdx, rdx
13:    idiv 10
14:    mov rax, rdx
15:    ret

For people that doesn't read assembly this is similar to:

int myfunc(int a)
{
    return a % 10;
}
Hen3
  • 175
  • 8
  • 3
    Consult an instruction set reference. There is no `idiv` that takes an immediate operand. You need to load into a register. – Jester Jun 12 '16 at 18:21
  • 2
    Most instructions don't take an immediate operand, it just seems that way because a bunch of very common ones do. Also, remainder by a constant is usually not implemented as an `idiv` but as magic number division for example: https://godbolt.org/g/OngMiM – harold Jun 12 '16 at 18:26

1 Answers1

3

As Jester mentioned. The idiv operation doesn't take immediate values as operands , the following code will work as expected.

10:  myfunc:
11:     mov  rax, rcx
12:     xor  rdx, rdx
13:     mov  rbx, 10
14:     idiv rbx
15:     mov rax, rdx
16:     ret
Hen3
  • 175
  • 8
  • 1
    This still has a more subtle bug: you're doing signed division after *zero*-extending the arg to 128-bit. If you actually wanted signed division, you should do `cdq`/`idiv`, otherwise you should do `xor edx,edx` / `div rcx` after `mov rax,rcx`. – Peter Cordes Oct 04 '22 at 09:49
  • 1
    Also this violates the calling convention: you modify the caller's RBX. Unlike RAX, RCX, and RDX which are call-clobbered in the standard calling conventions, RBX is call-preserved. So don't touch RBX, reuse RCX instead: `mov rax,rcx` / `cdq` / `mov ecx, 10` / `idiv rcx` / `mov rax, rdx`. – Peter Cordes Oct 04 '22 at 09:52
  • Correction, `cqo`/`idiv rcx` for 64-bit signed division. `cdq`/`idiv ecx` for 32-bit operand-size, dividing EDX:EAX by ECX. – Peter Cordes Oct 05 '22 at 04:34