Арифметическое отрицание эквивалентно вычитанию значения из 0, поэтому можно легко имитировать отрицание для очень больших чисел, используя инструкции sub и sbb:
.data ; 192-разрядное число number sqword 6, ; младшие 64 бита 0, ; средние 64 бита 0 ; старшие 64 бита .code main proc xor rax, rax ; RAX = 0 sub rax, number ; вычитание первых 64 бит mov number, rax mov rax, 0 sbb rax, number[8] ; вычитания вторых 64 бит с учетом флага CF mov number[8], rax mov rax, 0 sbb rax, number[16] ; вычитания старших 64 бит с учетом флага CF mov number[16], rax ret main endp end
В данном случае повледовательно вычитаем каждый из трех четверных слов числа number из 0 и сохраняем результат обратно в переменную number.
Если надо сделать отрицательным 128-разрядное число, то можно применять чуть более эффективный способ - комбинировать инструкции neg и sbb:
.data ; 192-разрядное число number qword 5, ; младшие 64 бита 0 ; старшие 64 бита .code main proc neg number[8], neg number sbb number[8], 0 ; если после neg установлен знак переноса ret main endp end
neg
фактически также вычитает операнд из 0, и если при вычитании младших 64 бит имело место заимствование, и соответственно был установлен флаг переноса CF, то также применяем инструкцию
sbb
для вычитания бита из старших 64 бит.
Для выполнения операции логического умножения AND для больших чисел просто выполняется операция AND между соответствующими байтами двух операндов с сохранением результата. Например, логическое умножение 192-разрядных чисел:
.data ; 192-разрядные числа n1 qword 5, 3, 2 n2 qword 4, 2, 3 result qword 3 dup(?) ; для хранения результата .code main proc mov rax, qword ptr n1 ; младший байт and rax, qword ptr n2 mov qword ptr result, rax mov rax, qword ptr n1[8] ; средний байт and rax, qword ptr n2[8] mov qword ptr result[8], rax mov rax, qword ptr n1[16] ; старший байт and rax, qword ptr n2[16] mov qword ptr result[16], rax mov rax, qword ptr result[0] ret main endp end
Аналогичным образом мы можем выполнять операции OR и XOR. Например, операция OR:
.data ; 192-разрядные числа n1 qword 5, 3, 2 n2 qword 4, 2, 3 result qword 3 dup(?) ; для хранения результата .code main proc mov rax, qword ptr n1 ; младший байт or rax, qword ptr n2 mov qword ptr result, rax mov rax, qword ptr n1[8] ; средний байт or rax, qword ptr n2[8] mov qword ptr result[8], rax mov rax, qword ptr n1[16] ; старший байт or rax, qword ptr n2[16] mov qword ptr result[16], rax mov rax, qword ptr result[8] ret main endp end
Для поразрядного отрицания применяем ко всем частям числа инструкцию neg:
.data ; 192-разрядное число num qword 0ffffffffffffffffh, 0fffffffffffffffeh, 0fffffffffffffffdh .code main proc neg qword ptr num ; младшие 64 бита neg qword ptr num[8] ; средние 64 бита neg qword ptr num[16] ; старшие 64 бита ret main endp end