How are types like int64_t implemented on the lowest i.e. assembly level? I'm using a 32 bit machine and still can use int64_t for example. My initial assumption is that the 64 bit are just simulated and thus there must be quite some overhead for computation with these types in comparison with 32 bit data types when being on a 32 bit machine.
Thank you in advance and Regards
You are right, when you compile code for 32 bit architectures, you have to simulate 64 bit operands and operations using 32 bit operands.
An 8-byte variable (uint64_t
which is just a typedef for long long
) is stored in 2 4-byte registers.
For adding (and subtracting), you have to first add the lower 4 bytes and then perform a second add with carry (or a subtract with borrow) on the higher 4 bytes. Since the second add also adds the carry from the first add, the result is correct. The overhead for adding and subtracting is not much.
For multiplying and division however, things aren't that simple. Usually a routine is called to perform these kind of operations, and the overhead is significantly bigger.
Lets take this simple c code:
int main() {
long long a = 0x0102030405060708;
long long b = 0xA1A2A3A4A5A6A7A8;
long long c = 0xB1B2B3B4B5B6B7B8;
c = a + b;
c = a - b;
c = a * b;
c = a / b;
return 0;
}
Analyzing the assembly generated by MSVC we can see:
2: long long a = 0x0102030405060708;
012D13DE mov dword ptr [a],5060708h
012D13E5 mov dword ptr [ebp-8],1020304h
3: long long b = 0xA1A2A3A4A5A6A7A8;
012D13EC mov dword ptr [b],0A5A6A7A8h
012D13F3 mov dword ptr [ebp-18h],0A1A2A3A4h
4: long long c = 0xB1B2B3B4B5B6B7B8;
012D13FA mov dword ptr [c],0B5B6B7B8h
012D1401 mov dword ptr [ebp-28h],0B1B2B3B4h
a 64 bit variable is split in 2 32-bit locations.
6: c = a + b;
012D1408 mov eax,dword ptr [a]
012D140B add eax,dword ptr [b]
012D140E mov ecx,dword ptr [ebp-8]
012D1411 adc ecx,dword ptr [ebp-18h]
012D1414 mov dword ptr [c],eax
012D1417 mov dword ptr [ebp-28h],ecx
7: c = a - b;
012D141A mov eax,dword ptr [a]
012D141D sub eax,dword ptr [b]
012D1420 mov ecx,dword ptr [ebp-8]
012D1423 sbb ecx,dword ptr [ebp-18h]
012D1426 mov dword ptr [c],eax
012D1429 mov dword ptr [ebp-28h],ecx
a sum is performed with an add
instruction on the lower 32 bits and then with an adc
(add with carry) for the higher 32 bits. Subtraction is similar: the second operation is sbb
(subtract with borrow).
8: c = a * b;
012D142C mov eax,dword ptr [ebp-18h]
012D142F push eax
012D1430 mov ecx,dword ptr [b]
012D1433 push ecx
012D1434 mov edx,dword ptr [ebp-8]
012D1437 push edx
012D1438 mov eax,dword ptr [a]
012D143B push eax
012D143C call __allmul (012D105Ah)
012D1441 mov dword ptr [c],eax
012D1444 mov dword ptr [ebp-28h],edx
9: c = a / b;
012D1447 mov eax,dword ptr [ebp-18h]
012D144A push eax
012D144B mov ecx,dword ptr [b]
012D144E push ecx
012D144F mov edx,dword ptr [ebp-8]
012D1452 push edx
012D1453 mov eax,dword ptr [a]
012D1456 push eax
012D1457 call __alldiv (012D1078h)
012D145C mov dword ptr [c],eax
012D145F mov dword ptr [ebp-28h],edx
The product and division are performed by calling special routines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With