这个字节操作的结果是什么?
What is the result of this byte operations?
我发现在 APDU 消息中,当您必须表示像 511 这样的数字时,您会写 0x01 0xFF 而不是 0x1FF。如果你想重新创建你做操作的号码
short number = (short) (b1<<8 | b2 & 0xFF);
其中 b1 为 0x01,b2 为 0xFF。为什么要做这个操作,b1<<8 和 b2 & 0xFF 的意义是什么?谢谢!
首先,我将重命名您的变量。 b1 将被称为 B1,b2 的重要性较低,在下面的代码中将被称为 B0。然后 b31 到 b0 将指示位位置,因为那是我习惯的。 b31 将是整数的最高位,b0 是最低位。
请注意,所有 Java 数学运算都会产生 int
。这与通常没有 int
的 Java Card 运行时一起玩得很开心,但让我们继续解释。
因此首先将字节转换为 int
。如果 B1
的最高位设置为 1
,则该字节为负值,b31 至 b8 位也将设置为 1
。这就是所谓的符号扩展 for Java。发生这种情况是因为 Java 中的所有整数都已签名(char
可能是个例外,但 Java Card 中无论如何都没有)。如果不是,如果 byte
值为负,您将得到不同的负 int
值。
B1 << 8
只是将字节的位置 b7 到 b0 的所有位(即所有位)移动到结果整数的位置 b15 到 b8。首先,字节被转换为整数。
对于您的计算,您将得到:
00000001 // B1 input, 0x01
00000000_00000000_00000000_00000001 // B1 as int
00000000_00000000_00000001_00000000 // B1 shifted 8 to the left
现在开始第二部分。好吧,首先我们必须使用符号位扩展再次转换为整数。但是,由于可能的符号位扩展,我们不能对先前的值使用 OR:b15 到 b8 中的所有最高位都将设置为 1!这就是为什么我们使用按位 AND 来屏蔽字节的所有位,以撤消符号扩展。
11111111 // B0 input, 0xFF (-1 decimal)
11111111_11111111_11111111_11111111 // B0 as int, with sign extension, (-1 decimal)
00000000_00000000_00000000_11111111 // B0 as int, after & 0xFF
太好了,现在我们对两者进行或运算(异或运算也可以,但是是的)
00000000_00000000_00000001_1111111 // B1 is now before B0
最后我们转换为 short
:
00000001_11111111 // which means removing the leftmost 16 bits
我们到了。
请注意,我们不必为 B1 执行 & 0xFF
技巧,因为我们在转换为 short 时无论如何都会丢弃位 b31 到 b16。因此,它们包含零值位还是一值位并不重要。
一个更具可读性的选项——在不需要优化的情况下——顺便简单地使用makeShort
。它很可能做完全相同的事情。
我发现在 APDU 消息中,当您必须表示像 511 这样的数字时,您会写 0x01 0xFF 而不是 0x1FF。如果你想重新创建你做操作的号码
short number = (short) (b1<<8 | b2 & 0xFF);
其中 b1 为 0x01,b2 为 0xFF。为什么要做这个操作,b1<<8 和 b2 & 0xFF 的意义是什么?谢谢!
首先,我将重命名您的变量。 b1 将被称为 B1,b2 的重要性较低,在下面的代码中将被称为 B0。然后 b31 到 b0 将指示位位置,因为那是我习惯的。 b31 将是整数的最高位,b0 是最低位。
请注意,所有 Java 数学运算都会产生 int
。这与通常没有 int
的 Java Card 运行时一起玩得很开心,但让我们继续解释。
因此首先将字节转换为 int
。如果 B1
的最高位设置为 1
,则该字节为负值,b31 至 b8 位也将设置为 1
。这就是所谓的符号扩展 for Java。发生这种情况是因为 Java 中的所有整数都已签名(char
可能是个例外,但 Java Card 中无论如何都没有)。如果不是,如果 byte
值为负,您将得到不同的负 int
值。
B1 << 8
只是将字节的位置 b7 到 b0 的所有位(即所有位)移动到结果整数的位置 b15 到 b8。首先,字节被转换为整数。
对于您的计算,您将得到:
00000001 // B1 input, 0x01
00000000_00000000_00000000_00000001 // B1 as int
00000000_00000000_00000001_00000000 // B1 shifted 8 to the left
现在开始第二部分。好吧,首先我们必须使用符号位扩展再次转换为整数。但是,由于可能的符号位扩展,我们不能对先前的值使用 OR:b15 到 b8 中的所有最高位都将设置为 1!这就是为什么我们使用按位 AND 来屏蔽字节的所有位,以撤消符号扩展。
11111111 // B0 input, 0xFF (-1 decimal)
11111111_11111111_11111111_11111111 // B0 as int, with sign extension, (-1 decimal)
00000000_00000000_00000000_11111111 // B0 as int, after & 0xFF
太好了,现在我们对两者进行或运算(异或运算也可以,但是是的)
00000000_00000000_00000001_1111111 // B1 is now before B0
最后我们转换为 short
:
00000001_11111111 // which means removing the leftmost 16 bits
我们到了。
请注意,我们不必为 B1 执行 & 0xFF
技巧,因为我们在转换为 short 时无论如何都会丢弃位 b31 到 b16。因此,它们包含零值位还是一值位并不重要。
一个更具可读性的选项——在不需要优化的情况下——顺便简单地使用makeShort
。它很可能做完全相同的事情。