Consider the following C function prototype, where num_t
is a data type declared using typedef:
void store_prod(num_t *dest, unsigned x, num_t y) {
*dest = x*y;
}
gcc generates the following assembly code implementing the body of the computation: What data type is num_t
?
The correct answer is that num_t
is unsigned long long
but I really don't understand why, any help will be greatly appreciated!!
# dest at %ebp +8, x at %ebp +12, y at %ebp +16
movl 12(%ebp), %eax
movl 20(%ebp), %ecx
imull %eax, %ecx
mull 16(%ebp)
leal (%ecx,%edx), %edx
movl 8(%ebp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
We can tell from the use of (%ebp)
addressing modes that this is 32-bit code, not x86-64.
In 32-bit mode, unsigned long long
is the only 64-bit unsigned integer type, in any of the common ABIs. (eg the i386 System V ABI, used on Linux). long
is 32-bit.
We can tell that num_t
is a 64-bit integer type because it's stored in two 32-bit halves from the result of integer multiply and addition.
We can tell that it's an unsigned
integer type because gcc used mul
instead of imul
between the x
and the low half of y
. (2-operand imul %eax, %ecx
to multiply x
with the upper half of y
is the same binary operation for signed or unsigned: only full-multiply (N x N => 2N bits) cares about signedness.)
IDK why gcc would use leal (%ecx,%edx), %edx
instead of add %ecx, %edx
. Maybe you compiled with -mtune=atom
or something? Preserving flags isn't necessary.
Anyway, it's an ordinary 64 x 32 => 64 bit extended-precision multiplication.
This is C, not C++, so a class wrapping a 64-bit integer with an overloaded *
operator can be ruled out, too.
We can rule out FP types because that would have used an FP multiply.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.