Reputation: 1538
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
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
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