Вычитание с учетом флага переноса и SBC

Последнее обновление: 16.07.2023

Инструкция SBC позволяют использовать флаг переноса в случае, если для вычитания требуется заимствование старшео разряда. В данном случае она применяется в паре с инструкцией SUBS. Сначала инструкция SUBS производит вычитание с установкой флага переноса C. А инструкция SBC вычитает дополнительно единицу, если флаг переноса не установлен (то есть результат отрицательный). Это может быть полезно, если в вычитании применяются числа больше 64 бит. Например, вычтем из 128-разрядного числа другое 128-разрядное число:

// пример вычитания 128-х разрядных чисел с помощью SUBS/SBC
.global _start

// первое 64-разрядное число - 0x0000000000000004 0000000000000002
_start: MOV X2, #0x0000000000000004
 MOV X3, #0x0000000000000002

// второе 64-разрядное число - 0x0000000000000001 0000000000000003
 MOV X4, #0x0000000000000001
 MOV X5, #0x0000000000000003

 SUBS X1, X3, X5    // вычитаем младшие 64 бита X1 = X3 - X5 
 SBC X0, X2, X4     // вычитаем старшие 64 бита X0 = X2 - X4

 MOV X8, #93            // номер функции Linux для выхода из программы - 93
 SVC 0                  // Вызываем функцию и выходим из программы

В данном случае мы получим следующую ситуацию:

0000000000000004 0000000000000002
-
0000000000000001 0000000000000003
=
0000000000000002 FFFFFFFFFFFFFFFF

Вычитание по шагам:

  1. Сначала выполняется вычитание младших битов:

    0x0000000000000002 - 0x0000000000000003
    

    Поскольку 2 меньше 3, то формально результат будет равен -1

    0xFFFFFFFFFFFFFFFF
    

    Поскольку результат отрицательный, инструкция SUBS сбрасывает флаг переноса. А число в реальности будет положительным:

    // в 16-системе
    FFFFFFFFFFFFFFFF
    // в 10-й системе
    18446744073709551615
    
  2. Далее выполняется вычитание старших битов, а также вычитается 1 бит, поскольку флаг переноса сброшен:

    0x0000000000000004 - 0x0000000000000001 - 1
    

    В итоге в регистре X0 будет

    0x0000000000000002
    

    А все 128-разрядное число будет равно

    0x0000000000000002 FFFFFFFFFFFFFFFF
    
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850