如何使用任意值左移一个字符以生成 64 位整数?

问题描述

我正在编写一个函数来计算字符串的 CRC *值。 ( * 8-64 的任意宽度)。 该函数接受 9 个参数,但为了说明左移的问题, 我只发布一个片段。

void leftshift(unsigned char* str,unsigned int n,int nshiftleft,unsigned __int64 *value)
{
  unsigned __int64 x = str[0];
  x = x << nshiftleft;
  *value = x;
}

如果 str[0] 是 "A" (65) 并且 nshiftleft 是 56, 我期望值是 0x4100000000000000 (65

void leftshift(unsigned char* str,unsigned __int64 *value)
{
  unsigned __int64 x = str[0];
  x = x << 56;
  *value = x;
}

如何实现?请帮忙。

编辑: 我是 Windows 用户,我打算使用脚本语言 AutoHotkey 中的此功能

以下代码工作正常: 字符串“AutoHotkey”的 CRC-64/ECMA_182 值 = 0x36990A8E358262B4

void crc64(unsigned __int64 r,unsigned char* s,int n,unsigned __int64 *value)
{
 unsigned __int64 poly = 0x42F0E1EBA9EA3693;
 unsigned __int64 t    = 0x8000000000000000;
 unsigned __int64 x    = 0;

  for (int i=0; i<n; i+=1)
  {
     x = (__int64)s[i];
     r ^= x << 56;
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
     r = (r & t) ? ( (r << 1) ^ poly ) : (r << 1);
   }

  *value = r;
}

以上是完整代码。我用 LCC x64 (windows) 将它编译为 .obj(没有任何错误/警告) 并提取如下的 .text 部分:

5589e583ec1c535657c745f89336eaa9c745fcebe1f042c745f000000000c745f400000080c745e800000000c745ec00000000c745e400000000e92c0200008b45108b55e40fb6041089c0998945e88955ec8b45e88b55ec89c2b800000000c1e21831450831550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f0235 5f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550c8b45088b550c2345f02355f483fa00750583f80074148b45088b550c0fa4c201d1e03345f83355fceb108b75088b7d0c89f089fa0fa4c201d1e089450889550cff45e48b45e43b45140f8cc8fdffff8b45188b4d088b5d0c89088958045f5e5b89ec5dc3

我能够使用 AutoHotkey 调用上述机器代码并获得正确的结果。 现在,我正在尝试使上述函数动态化,以便它可以处理 crc-8 到 crc-64 在一个函数中。

在这里一个用 AutoHotkey 编写的工作原型: https://www.autohotkey.com/boards/viewtopic.php?t=89364 (请向下滚动查看功能

循环迭代对于解释性语言来说非常慢,因此求助于 c 机器代码

感谢大家确认代码片段是正确的。 我将不得不检查 .obj 转储,但对 asm 一无所知。 我的结论是代码不能满足我的需要。

解决方法

当使用 Pelles C 编译时,以下在 x86 和 x64 中工作正常。 我将参数类型更改为 unsigned __int64 nshiftleft

void leftshift(unsigned char* str,unsigned int n,unsigned __int64 nshiftleft,unsigned __int64 *value)
{
  unsigned __int64 x = str[0];
  x = x << nshiftleft;
  *value = x;
}

以上适用于 LCC-win x64,但不适用于 x86。

@r3mainer

我认为问题在于我提取的机器代码没有以下行。

x = x << nshiftleft;

0x0000000000000041 的值来自它前面的行。

如果我创建 Windows DLL,我相信链接器会解决这个问题。 但这不是一个选项,因为我必须为 x86 和 x64 分别创建两个 DLL。 使用机器码方法,我可以简单地在嵌入为 base64/hex 文本的函数中包含/调用它们。

谢谢大家。

,

您不能通过移动 char 来创建 64 位整数。您需要创建一个 64 位数字并使用转换为 64 位的 char 对其进行初始化,然后您可以对其进行移位。不能移位大于字体大小的位数。