Search code examples
assemblyx86-64nasminteger-division

nasm idiv a negative value


Trying to divide a positive number by a negative number.

Currently my program will divide correctly, and I can correctly access the remainder.

But when I inputa positive number being divided by a negative value, it wont divide at all.

I know there is a way to "sign extend" and it will divide correctly. I just dont understand the manual

movsss $imm/%reg %reg/mem move, sign extend 231 movzss $imm/%reg %reg/mem move, zero extend

ofcourse thats att syntax, I need intel syntax

here is my code

xor rdx, rdx
mov rax, [input]
mov rcx, [input2]
idiv rcx

Ideas as how to divide by negative?


Solution

  • If the divisor is a signed 64-bit value, you don't need to do anything with it. Likewise, if the dividend is a signed 128-bit value, you don't need to do anything with it, just load the top 64 bits of it into rdx and the low 64 bits into rax.

    Now, if any of the numbers is signed but shorter than idiv expects, you need to sign-extend that number. Sign extension is very simple. You just fill the vacant top bits with the most significant bit (sign bit) of your number. For non-negative numbers you fill that space with 0's and for negative numbers you fill it with 1's. There are a few instructions available that can sign-extend the value currently held in the accumulator. They are: cbw, cwde, cdqe, cwd, cdq, cqo. The last three sign extend into dx/edx/rdx. Most likely you need cqo instead of xor rdx, rdx like this:

    mov rax, [input]
    cqo ; sign extends rax into rdx:rax
    mov rcx, [input2]
    idiv rcx
    

    As for 'But when I inputa positive number being divided by a negative value, it wont divide at all', it can't be. It either divides or invokes a division exception (division by 0 or overflow), there's no third option.