Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22207

How do constants for signed division differ from unsigned division when using reciprocal multiplication in assembly?

$
0
0

While using Godbolt Compiler, I was playing around with various functions when I checked what signed division looks like using the following code:

int div10(int num) {    return num / 10;}

Where the num/10 section generated the following assembly (RBP-4 is storing num at this point):

        mov     eax, DWORD PTR [rbp-4]        movsx   rdx, eax        imul    rdx, rdx, 1717986919        shr     rdx, 32        sar     edx, 2        sar     eax, 31        mov     ecx, eax        mov     eax, edx        sub     eax, ecx

I am aware that this is a typical example of division by reciprocal multiplication, using a fixed-point representation of 1/10 and bit shifts. What I do not understand is the choice of the constant 1717986919, or 0x6666_6667 in place of the typically cited (at least in Agner Fog's manual, https://www.agner.org/optimize/optimizing_assembly.pdf on page 138) constant 0xCCCC_CCCD. Note that the former is just the latter shifted to the left by one.

I can only assume that this has something to do with it being signed multiplication instead of unsigned multiplication, as the code generated when the type is uint32_t is as follows:

        mov     eax, DWORD PTR [rbp-4]        mov     edx, eax        mov     eax, 3435973837        imul    rax, rdx        shr     rax, 32        shr     eax, 3

Where 343597387 is the expected value 0xCCCC_CCCD.

I also do not fully understand the shifting and subtraction that occurs during the signed division example. The first two signed right-shifts are the standard discarding of the decimal (fractional? I do not know the proper terminology for this) bits. However, I do not know why eax, which as a reminder holds the original dividend, has its sign "extracted" (the sign bit is made to fill all the bits with an arithmetic shift) and then subtracted from the quotient. (Register shuffling occurs to force the desired output into eax since the return value must go in that register before the ret instruction executes.)

Sidenote: Unless Agner Fog has published new manuals, I could not find any mention of signed division in his book.


Viewing all articles
Browse latest Browse all 22207

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>