【问题标题】:Having difficulties understanding c++ program, shift , &难以理解 C++ 程序、shift 和
【发布时间】:2013-10-10 19:09:34
【问题描述】:

在我的机器语言课中,我们必须将 c++ 翻译成 mips,问题是我不太了解 c++,只是基本的东西,所以我很难理解这个功能:

void IPtoDD(int arg0, char *arg1)
{
  int temp, numChar, shift = 24;

  for (int i=0; i<4; i++) {
    temp = arg0 >> shift;
    temp = temp & 0x000000ff;
    numChar = byteToDec(temp,arg1);
    arg1 += numChar;
    *arg1++ = '.';
    shift -= 8;
  }

特别是

    temp = arg0 >> shift;
    temp = temp & 0x000000ff;

【问题讨论】:

  • 为什么不在调试器中一步一步地跟踪这段代码,看看发生了什么?你会学到更多是自己弄清楚而不是别人为你描述它。
  • 作为一个提示:我猜对于机器语言应该有一个可用的指令可以准确地为这些操作中的每一个执行此操作。

标签: c++ shift


【解决方案1】:

&gt;&gt; 运算符是“右移运算符”。它将左侧值的二进制表示向右移动 x 位,其中 x 是右侧的数字。这看起来像什么?以下是一些示例:

decimal: 128                   >> 1 == 64
binary:  0b0000 0000 1000 0000 >> 1 == 0b0000 0000 0100 0000

decimal: 64                    >> 1 == 32
binary:  0b0000 0000 0100 0000 >> 1 == 0b0000 0000 0010 0000

注意大二进制数中的 1 如何右移 1。在您的代码中,您将 arg0 移动了 shift,其中 arg0 是一些输入,shift 是 24、16、8 , 然后 0 因为你在循环。这意味着第一个循环,您将arg0 向下移动 24 位,然后将其存储到 temp 中。

第二个语句是按位与,它将左侧的每个位与右侧的每个相应位进行比较。如果两个位都为1,则相同位置的结果位为1,否则为0。以下是一些示例:

decimal: 7      & 15     == 7
binary:  0b0111 & 0b1111 == 0b0111

decimal: 5      & 12     == 4
binary:  0b0101 & 0b1100 == 0b0100

在您的表达式中,AND 使用右侧的值 0x000000FF 完成,它是 255 的十六进制等效值,以十进制表示。

您感兴趣的两个语句正在做什么,是从输入 arg0 中提取每个“字节”或“8 位块”:

temp = arg0 >> shift;
temp = temp & 0x000000ff;

Input:  arg0 = 0x12345678, shift = 24
Output: temp = 0x12

Input:  arg0 = 0x12345678, shift = 0
Output: temp = 0x78

关于右移的附录:

你在这里移动了一个 有符号 整数,但幸运的是你用下面的 AND 掩码屏蔽了这些位。为了完整起见,对有符号整数右移可以做两件事之一(假设这里是 16 位数字,32 位或 64 位数字的结果会有所不同):

算术右移:

decimal: -128                  >> 1 == -64
binary:  0b1111 1111 1000 0000 >> 1 == 0b1111 1111 1100 0000

逻辑右移:

decimal: -128                  >> 1 == 32704
binary:  0b1111 1111 1000 0000 >> 1 == 0b0111 1111 1100 0000

请注意算术右移如何“复制”最高位,其中“逻辑右移”导致零。 平台具体如何解释它,所以尽量远离它,并坚持移动无符号整数。

【讨论】:

    【解决方案2】:
    temp = arg0 >> shift
    

    这会对arg0 的内容进行二进制右移。它执行此转变shift 次数。所以从shift = 24 开始,它会向右移动arg0 24 次。

    temp = temp & 0x000000ff;
    

    这会掩盖temp 中包含的内容的最重要字节。最后一个字节仍然存在,因为任何&amp;'ed 和f 都只反映原始值。

    【讨论】:

      【解决方案3】:

      在这一行

      temp = arg0 >> shift;
      

      arg0 的值从最高有效位移动到最低位(注意它可能是从左到右或从右到左取决于 CPU 的字节序)移位值(第一次 24 然后 16 然后 8 )

      temp = temp & 0x000000ff;
      

      二进制与应用于临时,即除低位 8 位之外的所有位都重置为 0,低位 8 位不变。如果您需要在汇编中实现它,您可能不需要执行二进制 AND,而是获取正确的字节。

      【讨论】:

        【解决方案4】:
        temp = arg0 >> shift
        

        这有点偏移。整数值arg0 将向右移动shift 位数。

        例如,如果 shift = 8 且 arg0 = 0x1234,则 temp 将分配为 0x12。

        在您的代码中,如果 arg0 = 0x12345678 且 shift = 24,则 temp 变为 0x123456。

        temp = temp & 0x000000ff;
        

        这是一个按位的and 操作。十六进制数 0x0000000ff 用于在传递到 byteToDec() 之前屏蔽最低有效字节。

        所以在最后一个示例中,arg0 = 0x12345678,temp 被移动 24 到 = 0x123456,然后被屏蔽为 0x00000056。

        就 MIPS 而言, -- 右移逻辑变量 (SRLV) 指令将用于移位

        SRLV $d, $t, $s
        

        其中 $d 是目标寄存器,$t 是源寄存器,$s 是保存移位次数值的寄存器。值得理解的是,这种移位会从左侧引入零,并将更改有符号整数的值为负数,但是由于应用了一个掩码,它将零应用于除最低有效字节之外的所有字节,它可以并为您节省一些指令。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-12-12
          • 1970-01-01
          • 1970-01-01
          • 2014-07-12
          • 2011-08-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多