Сначала я переименую ваши переменные. b1 будет называться B1, а b2 имеет меньшее значение и будет называться B0 в приведенном ниже коде. Тогда от b31 до b0 будут указывать битовые позиции, потому что это то, к чему я привык. b31 будет наиболее значимой позицией целого числа, а b0 - наименее значимой позицией.
Обратите внимание, что все математические операции Java приводят к int
. Это играет чертовски весело с Java картой времени выполнения, которая обычно не имеет int
, но давайте продолжим объяснение.
Итак, сначала байт преобразуется в int
. Если самый верхний бит B1
установлен на 1
, то байт имеет отрицательное значение, а биты с b31 по b8 также будут установлены на 1
. Это называется расширение знака для Java. Это происходит потому, что все целые числа в Java подписаны (за возможным исключением char
, но в любом случае отсутствует в Java Card). Если этого не произойдет, вы получите другое отрицательное значение int
, если значение byte
было бы отрицательным.
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
Теперь для второй части. Что ж, сначала мы должны снова преобразовать в целое число, используя расширение знакового бита. Однако мы не можем использовать ИЛИ с предыдущим значением из-за возможного расширения знакового бита: все старшие биты от b15 до b8 будут установлены в 1! Вот почему мы маскируем все биты байта, используя побитовое И, чтобы отменить расширение знака.
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
Отлично, теперь мы ИЛИ два (XOR также будет работать, но да)
00000000_00000000_00000001_1111111 // B1 is now before B0
И, наконец, мы приводим к short
:
00000001_11111111 // which means removing the leftmost 16 bits
и вот мы здесь.
Обратите внимание, что нам не нужно выполнять трюк & 0xFF
для B1, потому что мы все равно выбрасываем биты с b31 на b16, когда бросаем на короткую позицию. Поэтому не имеет значения, содержат ли они нулевой или однозначный бит.
Более читаемый вариант - в случае, если оптимизация не требуется - просто использовать makeShort
с помощью путь. Скорее всего, он делает то же самое.