【问题标题】:How are the 64-bit types and operations implemented on the lowest level on a 32-bit architecture?64 位类型和操作是如何在 32 位架构的最低级别上实现的?
【发布时间】:2013-12-25 12:47:57
【问题描述】:

像 int64_t 这样的类型是如何在最低的(即汇编级别)上实现的?例如,我使用的是 32 位机器,但仍然可以使用 int64_t。我最初的假设是 64 位只是模拟的,因此在 32 位机器上与 32 位数据类型相比,这些类型的计算必须有相当多的开销。

提前谢谢你和问候

【问题讨论】:

  • 您可以查看您的编译器生成的汇编程序以找出...
  • 这实际上是一个简单但很棒的想法;)

标签: c++


【解决方案1】:

你是对的,当你为 32 位架构编译代码时,你必须模拟 64 位操作数和使用 32 位操作数的操作。

一个 8 字节变量(uint64_t 只是 long long 的一个 typedef)存储在 2 个 4 字节寄存器中。

对于加法(和减法),您必须先将低 4 个字节相加,然后在高 4 个字节。由于第二次加法还添加了第一次加法的进位,因此结果是正确的。加减的开销并不大。

然而,对于乘法和除法,事情并没有那么简单。通常会调用一个例程来执行这些操作,而且开销要大得多。


让我们来看看这个简单的 c 代码:

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;
}

分析MSVC生成的程序集我们可以看到:


     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  

一个 64 位变量被分成 2 个 32 位位置。


     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  

在低 32 位上使用 add 指令执行求和,然后在高 32 位上使用 adc(加进位)。减法类似:第二个操作是sbb(借位减法)。


     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  

通过调用特殊例程来执行乘积和除法。

【讨论】:

  • 感谢您的广泛回答。
猜你喜欢
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2015-09-26
  • 2020-12-20
  • 2010-11-19
相关资源
最近更新 更多