【问题标题】:How do I extract the operand from this byte? Using two's complement如何从这个字节中提取操作数?使用补码
【发布时间】:2017-12-15 00:38:52
【问题描述】:

我目前有代码:

int getOperand(unsigned char b) {
    int operand = b & 0x3F;
    return operand;
}

'b' 是一个从字节文件中读入的 8 位二进制数。 'b' 的最高 2 位是操作码,最后 6 位是操作数。我目前有这个代码设置来获取“b”的最后 6 位并将它们存储在变量“操作数”中。我目前遇到的问题是我不知道如何将操作数提取为有符号操作数。目前返回的数字只是无符号数。因此,如何编辑代码以使其返回有符号数字?

【问题讨论】:

    标签: c byte twos-complement


    【解决方案1】:

    如果我们假设您只是使用机器本机 2 的补码约定来存储负字节的最后 6 位,该负字节适合 6 位有符号值,用于表示负数,那么您检查是否在您的 6 中设置了符号位位值,然后扩展符号位。

    return (b & 0x20) ? b | ~0x3F : b & 0x3F;
    

    Try it online!

    【讨论】:

      【解决方案2】:

      我目前遇到的问题是我不知道如何提取 操作数作为有符号操作数。

      C 标准不强制规定任何特定的方式来表示负符号数。在大多数实现中,负符号整数存储在所谓的二进制补码中。存储负符号数的另一种主要方式称为反码。

      下面的代码假定输入的数字是作为有符号数字输入的,其中符号位存储为位 5 (0x20)。这称为一个补码表示。对于某些应用程序,以这种方式编写操作数更容易。 示例:

      #define NEGATIVE_SIGN      0x0C
      #define ONE                0x01
      #define TWO                0x02
      
      #define MINUS_ONE    (NEGATIVE_SIGN | ONE)
      #define MINUS_TWO    (NEGATIVE_SIGN | TWO)
      

      然后操作数被转换为二进制补码表示的完整 8 位 signed char。

      // INPUT: OPERAND in one's complement representation of the negative value.
      // Using 6 bits one can represent numbers from  -31 to 31.
      // returning `signed char` is presented in two's complement representation.
      
          signed char getOperand(unsigned char b) {
              unsigned char operand = b & 0x3F;
              unsigned char sign = 0x20 & operand;
              unsigned char number =  0x1F & operand;
      
              if(sign)
              {
                  number = (~number) +1;   // Conversion to Two's Complement     
              }
      
              return number;
          }
      
      
      //  5 4 3 2 1 0
      
      
      int main (){
          printf("%d\n",  getOperand(0x21)); // negative one
          printf("%d\n",  getOperand(0x22)); // -2
          printf("%d\n",  getOperand(0x2F)); // negative 15
          printf("%d\n",  getOperand(0x1F | 0x20 ) ); // negative -31    
          printf("%d\n",  getOperand(0x1F ) );        // positive 31 
      
        return 0;
      }
      

      输出:

      -1
      -2
      -15
      -31
      31
      

      【讨论】:

      • @chux 你是对的。明确说明signed 永远不会受到伤害!代码已得到改进。谢谢!
      • 不应该是0x3F == -1和0x20 == -32吗?
      • 你正在做一些补码计算。对于二进制补码,msb 不仅仅是一个符号位。
      • @Gerhardh OP 没有指定OPERAND 的输入表示。他只指定了所需的输出表示。代码假定 OPERAND,正如您正确指出的那样,在 one's complement representation 中。我在示例中添加了更多解释以阐明该方法。感谢您的好评。
      • 由于问题的标题提到了二进制补码,我认为应该使用表示。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 2017-10-19
      • 1970-01-01
      • 2019-08-15
      • 2015-04-08
      相关资源
      最近更新 更多