big_num1 dd 0x11111111, 0x22222222, 0x33333333
big_num2 dd 0xffffffff, 0x22222222, 0x33333333
Какие числа определены здесь?
Поскольку x86 - это архитектура с прямым порядком байтов, самая низкая часть числа хранится в памяти всамые низкие адреса.Для big_num1 первое определенное слово (значение 0x11111111) находится по самому низкому адресу и, следовательно, является самой низкой частью числа.В обычном представлении чисел это то, что идет справа:
big_num1 == 0x333333332222222211111111
big_num2 == 0x3333333322222222FFFFFFFF
Добавление больших чисел
Вы добавляете соответствующие цифры, идущие справа налево, как все учили в школе.
В шестнадцатеричном представлении этих чисел необходимо рассмотреть 24 цифры.Однако, поскольку архитектура 32-разрядная, мы можем сделать 3 группы по 8 цифр.
Для 1-й группы мы просто используем ADD
:
mov eax, [big_num1] ; 0x11111111
add eax, [big_num2] ; + 0xFFFFFFFF <-- This produces a carry
mov [result_4dword], eax ; 0x00000000
Для 2-й группы мыиспользуйте ADC
, чтобы подобрать возможный перенос из предыдущего дополнения:
mov eax, [big_num1 + 4] ; 0x22222222
adc eax, [big_num2 + 4] ; + 0x22222222 + CF=1 <-- No new carry
mov [result_4dword + 4], eax ; 0x44444445
Для 3-й группы мы используем ADC
, чтобы подобрать возможный перенос из предыдущего дополнения:
mov eax, [big_num1 + 8] ; 0x33333333
adc eax, [big_num2 + 8] ; + 0x33333333 + CF=0 <-- No new carry
mov [result_4dword + 8], eax ; 0x66666666
Превращая это в цикл
Ключ в том, что мы также можем использовать ADC
для 1-й группы , если мы явно очистим флаг переноса заранее:
clc
mov eax, [big_num1] ; 0x11111111
adc eax, [big_num2] ; + 0xFFFFFFFF + CF=0 <-- This produces a carry
mov [result_4dword], eax ; 0x00000000
Теперь мы можем написать цикл с 3 итерациями, но у нас есть , чтобы не допустить случайного изменения флага переноса .Вот почему я использую LEA
вместо ADD
, чтобы увеличить смещение.DEC
также инструкция, которая не уничтожает флаг переноса.Я предпочел комбо DEC ECX
JNZ ...
, потому что оно лучше, чем LOOP ...
:
mov ecx, 3
xor ebx, ebx ; This additionally clears the carry flag
Again:
mov eax, [big_num1 + ebx]
adc eax, [big_num2 + ebx] ; Can produce a new carry flag
mov [result_4dword + ebx], eax
lea ebx, [ebx + 4] ; This does not clobber the carry flag
dec ecx ; This does not clobber the carry flag
jnz Again
Если после этих 3 дополнений все еще есть набор переносов, вам придется написать 1 в 4-м dword result_4dword , иначе вам придется написать 0 здесь.Поскольку result_4dword находится в разделе .bss, вы не должны рассчитывать на любое заданное значение, например, ноль!
setc cl
mov [result_4dword + ebx], ecx ; ECX=[0,1]
Обратите внимание, что я изменил result_4word в result_4 d word .Имеет больше смысла ...