John Retallack
John Retallack

Reputation: 1538

IA-32 assembly divison

Can somebody explain to me the following snippet of assembly:

mydiv:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %edx  ; get x
        movl    %edx, %eax
        sarl    $31, %edx      ; divide by y
        idivl   12(%ebp)       ; return %eax
        popl    %ebp
        ret

This is the equivalent to the following C function:

int mydiv( int x, int y )
{
    return x / y;
}

The part which I'm having trouble understanding is the sarl instruction: why do you need to shift edx?

Upvotes: 0

Views: 2963

Answers (2)

Dariusz Wawrzyniak
Dariusz Wawrzyniak

Reputation: 21

It is worth noting that there is a dedicated instruction to fill EDX with 0s or 1s based on the sign bit of EAX.

cdq

Or in AT&T syntax, cltd (long to double-width?), but the GNU assembler accepts either mnemonic).
Use this before idiv; it implicitly reads EAX and writes EDX, sign-extending EAX into EDX:EAX as the dividend.

Before div, normally you want xor %edx,%edx to zero-extend EAX into EDX:EAX.

There are other widths available, like cbw to sign-extend AL into AX, and cqo to sign-extend RAX into RDX:RAX. What does cltq do in assembly? has an equivalence table between AT&T syntax and the mnemonics in Intel's manuals.

Upvotes: 2

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272687

It's sign extending.

idivl has a 64-bit argument (edx:eax), so you need to ensure that the MSB contains the correct sign bits, based on the msb of eax.

So if eax is positive, it's msb will be 0, e.g. 5 -> 0000 ... 0101. If it's negative it's msb will be 1, e.g. -5 -> 1111 ... 1011. sarl performs an arithmetic right-shift, so edx will either be 0000 ... 0000 or 1111 ... 1111.

Upvotes: 4

Related Questions