Я предполагаю, что вы уже знаете, что, например, 3 * 11
можно переписать как 3 * 1
+ 3 * 2
+ 3 * 8
. Эта последняя форма в основном соответствует тому, как код, который вы опубликовали, используется для вычисления результата.
Вы получили множитель и множитель в R0
и R1
;давайте назовем их X
и Y
, а также битовое число (0..31) в R3
;давайте назовем это N
.
Так что для каждого значения N
вы вычисляете X << N
, то есть X * 2^N
. Это действительно то, что делает CMP R3, #0
/ MOVNE R2, R2, LSL #1
. Сдвиг - это всего лишь один сдвиг влево, то есть удвоение текущего значения, но поскольку вы делаете это для каждой итерации, кроме первой, вы в итоге получаете X << N
.
Затем вы проверяете, если N
th бит Y
установлен:
(CMP R3, #0 )
MOVNE R4, R4, LSL #1 @ R4 = 1 << N == 1 * 2^N
TST R1, R4 @ Set flags based on Y & (1 * 2^N)
Если N
th бит Y
был установлен , вы добавляете X << N
к результату. Затем повторите для следующего значения N
и т. Д.
В случае 3 * 11
(двоичный 0011
* 1011
) у вас есть биты 0, 1 и 3, установленные в Y
,так что вы получите результат (3 << 0) + (3 << 1) + (3 << 3)
== 3*1 + 3*2 + 3*8
== 3 + 6 + 24
== 33
.