这个字节操作的结果是什么?

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。它很可能做完全相同的事情。