当超过32位

时间:2016-03-17 11:33:47

标签: c macos assembly x86 bit-manipulation

我只是在Mac OS X上进行了一些测试。但我不明白为什么会这样。

当我尝试对unsigned long long int应用一些按位运算时, 当某些操作超过32位时,没有关于操作的设备。

代码在下面..

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


#define KEY_MAX             31
#define INDEX_MASK          0b11111


unsigned long long int makePlain(unsigned long long int chipherText, int pattern);


static char testArray[] = {
    'A', 'B', 'C', 'D', 'E',
    'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y',
    'Z', ' ', '@', '@', '@' };


int main(void) {
    unsigned int i;
    unsigned long long int chipherText = 0b1010100100101010101111001000110101110101001001100111010;
    unsigned long long int plain = 0;

    for (i = 2; i <  3; i++) {
        plain = makePlain(chipherText, i);
        int j;
        for (j = 0; j < 11; j++) {
            printf("IDX=[%d] : %d\n", j,(unsigned int)(plain >> (5 * j) & INDEX_MASK));
        }

        printf("%c%c%c%c%c%c%c%c%c%c%c\n",
                testArray[(unsigned int)((plain >> (5 * 10)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 9)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 8)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 7)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 6)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 5)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 4)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 3)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 2)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 1)) & INDEX_MASK)],
                testArray[(unsigned int)((plain >> (5 * 0)) & INDEX_MASK)] );
    }

    return 0; }


unsigned long long int makePlain(unsigned long long int chipherText, int pattern) {
    int i;
    unsigned int temp;
    unsigned long long int plain = 0;

    for (i = 0; i < 11; i++) {
        temp = ((chipherText >> (5 * i)) & INDEX_MASK);
        temp = temp ^ pattern;
        printf("[%d]:temp -after xor : %d\n", i, temp);
        plain |= (temp << (5 * i)); // Here is make problems.
    }

    return plain; }

(起初,代码不好看......对不起大家。)

请参阅makePlain函数的最后一行循环..

当变量i为6时,它的写位超过32位。 之后,“plain | =”的所有操作都不适用,但对于32位以上的位保持为0。

下面是Xcode Debbugger的结果。

enter image description here

所以,我只是确认了asm,我发现了那种代码..

      call    printf
  LM42:
      movl    -4(%rbp), %edx          # i -> edx
      movl    %edx, %eax              # eax = i
      sall    $2, %eax                # i * 4
      addl    %edx, %eax              # i * 5
      movl    -20(%rbp), %edx         # temp -> edx (maybe problem
                                      # becase it load 64bit on 32)
      movl    %eax, %ecx              # eax -> ecx ==> ecx = i * 5
      sall    %cl, %edx               # edx << i * 5 //why 32 bit? 
      movl    %edx, %eax              # eax saving (plain) //why 32bit
      movl    %eax, %eax              # 
      orq>%rax, -16(%rbp)             # saving

我认为上面的代码是

  

plain | =(temp&lt;&lt;(5 * i));

关于makePlain函数。

我的问题是......

  • 为什么会这样? (我认为当它们被移位时它被编译为32位寄存器。并且当我看到asm代码时它们加载......)
  • 如果我的thike是正确的..什么样的complie选项可以解决这个问题?
  • 如何在Xcode调试器上看到汇编代码?

2 个答案:

答案 0 :(得分:2)

您的temp变量只有32位,因为它是unsigned int。将其类型更改为unsigned long long以解决您的问题。

会发生什么?

在这一行:

plain |= (temp << (5 * i));

变量temp具有unsigned int类型,通常为32位类型。因此,左移位也是32位移位,并且丢弃超出32位的移位。该代码还表现出不确定的行为时i是大于6,通过多个位比其类型移值具有未定义。

有两种方法可以解决这个问题。一种是给temp正确的类型,另一种是使用适当的强制转换以确保班次是unsigned long long班次:

plain |= ((unsigned long long)temp << (5 * i));

答案 1 :(得分:1)

在编写代码时,请始终确保所有变量彼此依赖的数据类型相同。在这种情况下,它可以避免内存溢出