【问题标题】:Concatenation of multiple HEX values in CC中多个十六进制值的连接
【发布时间】:2017-08-26 06:00:10
【问题描述】:

我在内存中有一个数组,其中包含描述汇编指令的某些十六进制值。例如:

708877665544332211 = jump 0x1122334455667788

70 表示汇编中的跳转,以下十六进制数字是我需要连接的。我已经试过了,

address |= memory[1];
address |= memory[2]<<8;
address |= memory[3]<<16;
address |= memory[4]<<24;
address |= memory[5]<<32;
address |= memory[6]<<40;
address |= memory[7]<<48;
address |= memory[8]<<56;

输出的字符串是:

0x100: 708877665544332211 |跳转1432778700

我在连接中哪里出错了?

编辑:按照本杰明的建议,我将其更改为:

使用打印语句printf("APPEND: %016llx", address)进行调试,我发现uint64_t被更改为:

APPEND: 0000000000002211
APPEND: 0000000000332211
APPEND: 0000000044332211
APPEND: 0000000044332255
APPEND: 0000000044336655
APPEND: 0000000044776655

如果地址是 64 位整数,为什么它看起来像 32 位整数?

【问题讨论】:

  • 我想观察一下为什么您的代码在第一种情况下无法按预期工作:关于address |= memory[5]&lt;&lt;32;address |= memory[6]&lt;&lt;40;address |= memory[7]&lt;&lt;48;address |= memory[8]&lt;&lt;56;存在整数提升的问题。例如,address |= memory[5]&lt;&lt;32; 会将 memory[5] 提升为 int(在您的平台上为 32 位值)。如果您尝试将超过 32 位类型宽度的 32 位左移。这将导致未定义的行为,这也是您在address 中获得异常结果的原因
  • 您可以使用 address |= ((unsigned long long)memory[5])&lt;&lt;32 之类的内容进行投射。这会将 memory[5] 转换为 64 位类型,然后对其执行移位。假设您将address 定义为unsigned long long
  • 我有点惊讶,尽管编译器不会在编译时警告你这个问题。

标签: c assembly hex concatenation


【解决方案1】:

十六进制的十进制数 1432778700 是 0x556677CC。这很可能是变量“地址”的数据类型的问题。它必须能够容纳 8 个字节。所以你必须使用像unsigned long long int这样的数据类型。

一旦你解决了这个问题,那么你需要知道地址是按little endian还是big endian的顺序存储在内存中的,并进行相应的处理。

更新: 刚刚看到您编辑的问题。 如果您期望以下转换: 708877665544332211进入0x1122334455667788

那么即使是这样的事情也会起作用:

unsigned char bMemory[] = {0x70,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};

int main()
{
    unsigned long long int address = *((unsigned long long int *)(&bMemory[1]));
    printf("\n Address is %llX", address );

    return 0;
}

【讨论】:

  • 这将违反 C 的 strict aliasing rules
  • @MichaelPetch 在其中一个 cmets 中有“char * 不会破坏它,因为它可以重新输入任何东西”......(我不知道什么是正确的,但我打破了当我需要以不同的方式处理相同的内存内容时,通常会使用严格的别名规则:/ ....旧习惯很难改掉,如果你看到的只是一点点......)
  • @Ped7g 在这种情况下,您通过unsigned long long 的指针访问bMemory 数组(它是一个字符数组)的元素。这违反了严格的别名。如果您有相反的指针,例如指向 unsigned long long 的指针,则别名规则的异常将允许您通过 char * 访问 unsigned long long 的每个字节。
  • 在这种情况下,我可能会考虑像这样使用 memcpy unsigned long long address; memcpy (&amp;address, bMemory+1, sizeof (address)); 。如果使用内置和优化,这应该减少到合理的代码。
【解决方案2】:

问题在于字节顺序。也许您可以尝试以下方法:

address = memory[8];
address |= memory[7]<<8;
address |= memory[6]<<16;
address |= memory[5]<<24;
address |= memory[4]<<32;
address |= memory[3]<<40;
address |= memory[2]<<48;
address |= memory[1]<<56;

P.S.:如果您将代码发布完整代码(包括打印)会有所帮助。

【讨论】:

    【解决方案3】:

    我发现我做错了什么。我应该只是附加这些位,然后每次将它们向下移动 8 位。

    for(int i = 8; i < 0; i--){
      address<<=8;
      address |= memory[i];
    }
    

    【讨论】:

    • 0 &lt; i ...这没有意义...我知道,你必须先将memory[8]转换为64b,然后再&lt;&lt;56。至少 gcc 发出警告:"[x86-64 gcc 6.3] warning: left shift count >= width of type [-Wshift-count-overflow]" ...你在使用-Wall吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 2011-06-01
    • 2014-11-30
    • 2016-08-07
    • 2011-12-09
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多