Поразрядные операции с большими числами

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

Арифметическое отрицание

Арифметическое отрицание эквивалентно вычитанию значения из 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, OR, XOR

Для выполнения операции логического умножения 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
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850