简体   繁体   English

超过32位时不应用无符号long long int的按位运算

[英]Bitwise operation for unsigned long long int is not applied when it's over 32bits

I'm just some test on Mac OS X. But I don't understand why this happens. 我只是在Mac OS X上进行测试。但是我不明白为什么会这样。

when I try to apply some bitwise operation on unsigned long long int, when some operation is over 32bit, there's no appliance about the operation. 当我尝试对unsigned long long int应用按位运算时,当某些运算超过32bit时,该运算没有任何作用。

the code is below.. 代码在下面。

#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; }

(at first, the code isn't good to see.. sorry everyone.) (起初,代码不好看..对不起大家。)

Please see the last line of loops on makePlain function.. 请参阅makePlain函数的最后一行循环。

when variable i is 6, it's write bits over 32 bits. 当变量i为6时,它将写入32位以上的位。 after that, all operation of "plain |=" isn't apply but remain as 0 about bits over 32bits. 之后,“ plain | =“的所有运算都不适用,但对于32位以上的位,其保持为0。

below is Xcode Debbugger result. 以下是Xcode Debbugger的结果。

在此处输入图片说明

So, I just confirm the asm and i found that kind of code.. 所以,我只是确认了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

I think above code is 我认为上面的代码是

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

on makePlain function. 在makePlain函数上。

My question is.. 我的问题是..

  • Why this happen? 为什么会这样? (I think it's complied as 32 bit register when they're shifted. and they load... when i see asm code..) (我认为当它们移位时,它被编译为32位寄存器。当我看到asm代码时,它们就加载了。)
  • if my thiking is correct.. what kind of complie option solve that happen? 如果我的想法是正确的..什么样的complie选项可以解决这种情况?
  • How can I see the assemble code on Xcode debugger? 如何在Xcode调试器上查看汇编代码?

Your temp variable only has 32 bits as it is an unsigned int . 您的temp变量只有32位,因为它是一个unsigned int Change its type to unsigned long long to solve your problem. unsigned long long将其类型更改为unsigned long long即可解决您的问题。

What happens? 怎么了?

In this line: 在这一行:

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

The variable temp has unsigned int type which is typically a 32 bit type. 变量temp具有unsigned int类型,通常为32位类型。 The left shift is therefore also a 32 bit shift and whatever is shifted beyond 32 bits is discarded. 因此,左移位也是32位移位,任何超出32位的移位都将被丢弃。 The code also exhibits undefined behaviour when i is greater than 6 as shifting a value by more bits than its type has is undefined. i大于6时,该代码还表现出不确定的行为,因为将一个值移位超过其类型所未定义的位数。

There are two ways to solve this. 有两种解决方法。 One is to give temp the right type, the other is to use an appropriate cast to make sure that the shift is an unsigned long long shift: 一种是给temp正确的类型,另一种是使用适当的强制转换以确保该移位是unsigned long long移位:

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

When you are writing your code always make sure that all the variables depend on each other should be in same datatype. 在编写代码时,请始终确保彼此依赖的所有变量都应位于同一数据类型中。 It avoids memory overflow in such cases 这样可以避免内存溢出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM