Инструкция 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
Вычитание по шагам:
Сначала выполняется вычитание младших битов:
0x0000000000000002 - 0x0000000000000003
Поскольку 2 меньше 3, то формально результат будет равен -1
0xFFFFFFFFFFFFFFFF
Поскольку результат отрицательный, инструкция SUBS сбрасывает флаг переноса. А число в реальности будет положительным:
// в 16-системе FFFFFFFFFFFFFFFF // в 10-й системе 18446744073709551615
Далее выполняется вычитание старших битов, а также вычитается 1 бит, поскольку флаг переноса сброшен:
0x0000000000000004 - 0x0000000000000001 - 1
В итоге в регистре X0 будет
0x0000000000000002
А все 128-разрядное число будет равно
0x0000000000000002 FFFFFFFFFFFFFFFF