Эту команду можно использовать для вычитания 64-разрядных чисел на 32-разрядных процессорах, или 32-разрядных чисел на 16-разрядных процессорах.
В первом случае можно использовать пары регистров EDX:EAX и EBX:ECX, а во втором DX:AX и BX:CX. Если при вычитании значений в младших регистрах произошёл заём, то он будет учтён при вычитании старших слов.
Пример:
.model tiny
.code
ORG 100h
start:
MOV DX, 1 ;В паре DX:AX (0001:0000)
MOV AX, 0 ;32-разрядное число 65536
MOV BX, 0 ;В паре BX:CX
MOV CX, 1 ;32-разрядное число 1
;65536 - 1 = 65535, то есть после вычитания
;DX:AX = 65535 (0000:FFFF)
SUB AX, CX ;AX = FFFF
SBB DX, BX ;DX = 0000
RET
END start
В этом примере мы используем 16-разрядные регистры для выполнения операции вычитания 32-разрядных чисел.
В паре регистров DX:AX у нас будет число 65536 (00010000h), которое не помещается в один 16-разрядный регистр.
От этого числа мы отнимаем число 1. Это число можно отнять как непосредственное значение, но для понимания того, что можно отнять любое другое 32-разрядное число, мы поместим единицу в пару регистров BX:CX (число будет 00000001h).
Затем сначала мы из младшего регистра первого числа вычитаем младший регистр второго числа с помощью команды SUB. Результат будет равен FFFF, поскольку мы от нуля отнимаем единицу, а флаг переноса CF будет установлен.
Затем с помощью команды SBB мы от старшего регистра первого числа отнимаем старший регистр второго числа (от единицы мы отнимаем ноль). Если бы мы использовали команду SUB, то в регистре DX мы бы получили 1. То есть пара DX:AX содержала бы 32-разрядное число 1FFFFh (131071 в десятичной):
65536 - 1 = 131071
что, разумеется, неправильно.
Но мы используем команду SBB, которая кроме того, что вычитает в нашем примере из DX значение BX, ещё отнимает от результата значение флага переноса (которое в нашем примере равно 1). В итоге получаем правильное значение DX:AX = 0000:FFFF = 65535.
Ну и напоследок, как всегда, о происхождении аббревиатуры SBB.
SBB - это SuBtract with Borrow - вычитание с заимствованием.