• WP8.1中C++的winodws运行时组件位移操作的差异


      最近学习WP8.1应用开发,想把C语言的SM3国密算法移植到手机app中。由于把C语言的代码转换成C#代码工作量较大,因此只能用winodws运行时组件来实现。

      SM3国密算法是一种HASH算法,具体详情请自行百度。

      结果测试发现手机上SM3算法计算出来的结果和电脑上运行的结果不同!经过我一点点调试发现是位移操作惹的祸,代码中有如下宏定义:

    #define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
    #define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
    

       第一行的宏定义当n大于32时,手机运算结果与电脑不同;第二行的宏定义当32-n小于0时,手机运算结果与电脑不同。

      为了更好地测试,我决定建一个干净的测试环境。首先新建一个C#语言的空白的windows phone应用项目,在xaml中放一个textblock和2个按钮

    <Grid>
            <StackPanel>
                <TextBlock x:Name="txbResult"/>
                <Button x:Name="btnCSharpLeft" Content="C#位移" Click="btnCSharpLeft_Click"></Button>
                <Button x:Name="btnCLeft" Content="C左位移" Click="btnCLeft_Click"></Button>
            </StackPanel>
        </Grid>

    再实现按钮点击事件

    private void btnCSharpLeft_Click(object sender, RoutedEventArgs e)
            {
                txbResult.Text += "C#位移
    ";
                for (int i = 0; i < 96; i += 8)
                {
                    string str = "0x12345678<<" + i.ToString() + "=" + (0x12345678 << i).ToString("X");
                    txbResult.Text += str.PadRight(40) + "0x12345678>>" + i.ToString() + "=" + (0x12345678 >> i).ToString("X") + "
    ";
                }
            }
    
            private void btnCLeft_Click(object sender, RoutedEventArgs e)
            {
                txbResult.Text += "C位移
    ";
                Class1 c = new Class1();
                for (int i = 0; i < 96; i += 8)
                {
                    string str = "0x12345678<<" + i.ToString() + "=" + c.Func2(0x12345678, i).ToString("X");
                    txbResult.Text += str.PadRight(40) + "0x12345678>>" + i.ToString() + "=" + c.Func1(0x12345678, i).ToString("X") + "
    ";
                }
            }

    接着新建一个C++语言的windows运行时组件,对外提供两个函数,用以实现左位移和右位移

    unsigned int Class1::Func1(unsigned int n, int b)
    {
        return n >> b;
    }
    
    unsigned int Class1::Func2(unsigned int n, int b)
    {
        return n << b;
    }

    然后连上手机进行测试,我的手机是nokia920,公司测试部的测试机,先拿来用用,吼吼!

      可以看到C#的位移在超过32时是对32取模的,也就是说位移33位相当于位移1位,而手机上运行结果测试超过32位都是0!

    为了确定是否C++语言的位移都是这么处理的,我再新建一个WIN32的控制台项目来测试

    #include "stdio.h"
    
    int main()
    {
        printf("C左移
    ");
        for (int i = 0; i < 96; i += 8)
        {
            printf("0x12345678<<%d = %x
    ",i,0x12345678 << i);
        }
        printf("C右移
    ");
        for (int i = 0; i < 96; i += 8)
        {
            printf("0x12345678>>%d = %x
    ", i, 0x12345678 >> i);
        }
        return 0;
    }

    运行结果如下

    可以看到和C#的结果是一样的。说明只有C++的windows运行时组件中才会有不同的结果。

    同理我再测试位移负数位,比如 0x12345678>>-2,在C#和C++的WIN32程序中位移-2位相当于位移30位,而在C++的windows运行时组件中则结果是0。

    结论:为了兼容性,位移时要对32取模,比如1>>n要写成1>>(n%32),这样在不同的平台中也能得到相同的结果。

  • 相关阅读:
    Golang gRPC学习(01): gRPC介绍
    MySQL InnoDB存储引擎大观
    SpringBoot学习-图文并茂写Hello World
    Golang的goroutine协程和channel通道
    业务 产品 技术的一点看法
    需求一直做不完,怎么办?
    技术管理:项目开发中的几种风险管理
    go内存管理
    etcd实现分布式锁分析
    强缓存与协商缓存
  • 原文地址:https://www.cnblogs.com/jintianhu/p/4075024.html
Copyright © 2020-2023  润新知