比较32位微控制器上的两个64位变量

时间:2018-09-21 06:05:52

标签: c int 32-bit

我遇到以下问题:我有两个64位变量,必须尽快比较它们,我的微控制器只有32位。

我的想法是,有必要像这样将64位变量分为两个32位变量

uint64_t var = 0xAAFFFFFFABCDELL;
hiPart = (uint32_t)((var & 0xFFFFFFFF00000000LL) >> 32);
loPart = (uint32_t)(var & 0xFFFFFFFFLL);

然后比较hiParts和loParts,但是我确信这种方法很慢并且有更好的解决方案

4 个答案:

答案 0 :(得分:3)

第一个规则应该是:编写您的程序,以便人类可以阅读

如有疑问,请不要假设任何东西,而要进行测量。让我们看看godbolt给我们带来了什么。

#include <stdint.h>
#include <stdbool.h>

bool foo(uint64_t a, uint64_t b) {
    return a == b;
}

bool foo2(uint64_t a, uint64_t b) {

    uint32_t ahiPart = (uint32_t)((a & 0xFFFFFFFF00000000ULL) >> 32);
    uint32_t aloPart = (uint32_t)(a & 0xFFFFFFFFULL);
    uint32_t bhiPart = (uint32_t)((b & 0xFFFFFFFF00000000ULL) >> 32);
    uint32_t bloPart = (uint32_t)(b & 0xFFFFFFFFULL);

    return ahiPart == bhiPart && aloPart == bloPart;
}

foo:
        eor     r1, r1, r3
        eor     r0, r0, r2
        orr     r0, r0, r1
        rsbs    r1, r0, #0
        adc     r0, r0, r1
        bx      lr

foo2:
        eor     r1, r1, r3
        eor     r0, r0, r2
        orr     r0, r0, r1
        rsbs    r1, r0, #0
        adc     r0, r0, r1
        bx      lr

如您所见,它们会产生完全相同的汇编代码,但是您可以决定哪个更不容易出错并且更容易阅读?

答案 1 :(得分:1)

几年前的某个时候,您需要做一些技巧,以使其比编译器更聪明。但是在99.999%的情况下,编译器将比您更聪明。

并且您的变量是无符号的。因此,请使用ULL而不是LL

答案 2 :(得分:1)

最快的方法是让编译器执行此操作。大多数编译器在微观优化方面比人类要好得多。

uint64_t var = …, other_var = …;
if (var == other_var) …

没有很多方法可以解决这个问题。在后台,编译器将安排将每个变量的高32位和低32位加载到寄存器中,并比较两个包含高32位的寄存器和两个包含低32位的寄存器。汇编代码可能看起来像这样:

load 32 bits from &var into r0
load 32 bits from &other_var into r1
if r0 != r1: goto different
load 32 bits from &var + 4 into r2
load 32 bits from &other_var + 4 into r3
if r2 != r3: goto different
// code for if-equal
different:
// code for if-not-equal

以下是编译器比您更了解的一些内容:

  • 根据周围代码的需要使用哪个注册。
  • 是重用相同的寄存器来比较上下部分,还是使用不同的寄存器。
  • 是先处理一个部分,然后处理另一部分(如上所述),还是先加载一个变量,然后再加载另一个变量。最佳顺序取决于寄存器上的压力以及特定处理器模型的内存访问时间和流水线处理。

答案 3 :(得分:0)

如果您使用工会,则可以在不进行任何额外计算的情况下比较“高”和“低”零件:

typedef union
{
    struct
    {    
        uint32_t   loPart;
        uint32_t   hiPart;
    };
    uint64_t       complete;
}uint64T;

uint64T var.complete = 0xAAFFFFFFABCDEULL;